鉴于此irb会议:
[2.0.0p195]> arr = [{count: 5}, {count: 6}, {count: 7}]
=> [{:count=>5}, {:count=>6}, {:count=>7}]
[2.0.0p195]> arr.collect(&:count)
=> [1, 1, 1]
笏
[2.0.0p195]> arr.collect(&:count).reduce(:+)
=> 3
[2.0.0p195]> arr.collect {|e| e[:count]}.reduce(:+)
=> 18
我可以在collect
或使用阻止时解决Hash上的方法解决此问题的唯一方法吗?
答案 0 :(得分:3)
&安培;表示在其参数上调用#to_proc
,在Symbol class implements this上创建一个基于符号调用方法名称的Proc - 所以&:symbol
表示“在传入的对象上调用#symbol方法”。基本上,你得到的就是这相当于:
arr.collect{|obj| obj.send(:count)}
由于Hash根本不会响应“count”方法来获取:count键的值 - 也就是说,Hash#count
与Hash#[](:count)
不同,(尽管{{ 3}}确实为你做了这个),你坚持使用块方法。
答案 1 :(得分:2)
另一种方法是创建一个lambda,如果您多次编写同一个块,则非常有用:
fetch_count = -> x{x[:count]}
arr.collect(&fetch_count) #=> [5, 6, 7]
# If hash only has one value as in example:
arr.collect(&values).flatten #=> [5, 6, 7]
答案 2 :(得分:2)
呼叫&的实施在符号上如下(或多或少):
class Symbol
def to_proc
Proc.new { |obj| obj.send self }
end
end
你可以看到它所做的一切(当与#map
结合使用时)正在调用与枚举的每个成员上提供的符号相对应的方法。
如果你真的想通过使用OpenStruct
而不是哈希来解决这个问题,你可以通过方法式访问元素来解决这个问题:
[{test: 1}].map { |h| OpenStruct.new(h) }.map &:test
#=> [1]
或者发明一个除&
之外还要执行哈希访问所需操作的运算符,如果稍后我有空闲时间,我可以重新审视这个挑战!
编辑:我已退回
这很hacky但是你可以通过使用一元~
进行扩充来修补符号以提供你想要的功能:
# Patch
class Symbol
def ~@
->(obj){ obj[self] }
end
end
# Example usage:
[{count: 5}, {count: 6}, {count: 7}].map &~:count
#=> [5, 6, 7]
如果像Ruby这样的免费语言没有您想要的功能,您可以随时将其构建: - )
免责声明:这可能是一个糟糕的主意。