我在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
"移除"了"放置"的阵列括号。 也许不是最合适的思考方式? 它确实有助于消除我的困惑。
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"时,您是在说"设置orders
以引用直接传入的任何内容"。在本例中,您将向其传递一个哈希,当您迭代哈希时,您将获得每个条目的键/值对。这正是您想要的。
但是,当您确实拥有splat时,您将获得以下信息:
def cost(*orders)
p orders.class #=> Array
p orders #=> [{:rice=>1, :noodles=>1}]
end
orders = {:rice=>1, :noodles=>1}
cost(orders)
因此,您将哈希包装在一个数组中,然后迭代数组的元素。因此,传递给块的第一个值是整个哈希值,并且没有第二个参数。
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
,因此您的代码会中断。