ruby - 为什么仅当我从参数中删除 splat 运算符时,Hash#each 方法的这种使用才有效?

标签 ruby hash inject splat

我正在解决 Ruby Monk 的问题,https://rubymonk.com/learning/books/1-ruby-primer/problems/155-restaurant#solution4804

他们的解决方案很棒;我喜欢它,它比我的更紧凑。问题出在我身上,我只是不明白为什么只有当我从成本参数 orders 中删除 splat 运算符时它才有效。即使我不应该这样做,我也在努力弄清楚发生了什么。我知道有时候没有必要了解所有内容,最好继续前进..但好奇。

这是我的:

class Restaurant
  def initialize(menu)
    @menu = menu
  end

  def cost(*orders)
    total_cost = 0
    orders.each do |item, number|
    total_cost += @menu[item] * number
  end
end

menu = {:rice => 3, :noodles => 2}
orders = {:rice => 1, :noodles => 1}
eat = Restaurant.new(menu)
puts eat.cost(orders)

编辑: 在下面包含他们建议的解决方案

class Restaurant
  def initialize(menu)
    @menu = menu
  end

  def cost(*orders)
    orders.inject(0) do |total_cost, order|
      total_cost + order.keys.inject(0) {|cost, key| cost + @menu[key]*order[key] }
    end
  end
end

编辑: 在评论中澄清并回答我自己的问题

我尝试了这些实验,它显示 inject “移除”了 splat “穿上”的数组括号。也许不是最恰当的思考方式?它确实有助于消除我的困惑。

order = { :rice => 1, :noodles => 1 }
menu = { :rice => 3, :noodles => 2 }

[order].inject(0) do |bla, blu|
    p bla       #=> 0
    p blu       #=> {:rice=>1, :noodles=>1}
    p blu.keys  #=> [:rice, :noodles]
end

最佳答案

当你写的时候:

def cost(*orders)
end

然后所有传递给 cost 方法的参数将被放入一个名为 orders 的数组中。因此这两个是等价的:

def cost(*orders)
  p orders.class #=> Array
  p orders       #=> [1,2,3]
end
cost(1,2,3)

def cost(orders)
  p orders.class #=> Array
  p orders       #=> [1,2,3]
end
cost( [1,2,3] )     # note the array literal brackets

在您的情况下,当您删除“splat”时,您说的是“设置订单以引用直接传入的任何内容”。在这种情况下,您向它传递一个散列,当您迭代一个散列时,您将获得每个条目的键/值对。这正是您想要的。

不过,当你确实有 splat 时,你会得到这个:

def cost(*orders)
  p orders.class #=> Array
  p orders       #=> [{:rice=>1, :noodles=>1}]
end
orders = {:rice=>1, :noodles=>1}
cost(orders)

因此,您将散列包装在一个数组中,然后遍历该数组的元素。因此,传递给区 block 的第一个值是整个哈希值,没有第二个参数。

def cost(*orders)
  p orders.class #=> Array
  p orders       #=> [{:rice=>1, :noodles=>1}]
  orders.each do |item,number|
    p item       #=> {:rice=>1, :noodles=>1}
    p number     #=> nil
  end
end
orders = {:rice=>1, :noodles=>1}
cost(orders)

此时您不能将任何值乘以 nil,因此您的代码会中断。

关于ruby - 为什么仅当我从参数中删除 splat 运算符时,Hash#each 方法的这种使用才有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21744447/

相关文章:

html - 真的允许通过 CSS 导入文本吗?

ruby - 在 Ruby 中,将 "chomp"放在字符串开头而不是结尾的最简单方法是什么?

ruby-on-rails - Nokogiri 依赖项 libxml 和 libxslt 未安装

hash - 硬件 token 设备如何工作?

algorithm - 数学组合的完美最小散列

c++ - 尝试打印文件的十六进制 Blake2 哈希时出现一个非常奇怪的错误

c - 第三台计算机在 dst 计算机从 src 计算机接收数据包之前使用 libpcap 捕获、修改和注入(inject)数据包

ruby-on-rails - 递归 Rails 嵌套资源

ruby - 匹配中多个期望语句的自定义断言消息

mysql - Wildfly 10 持久化 MySQL 表未找到