如何使用Symbol#to_proc
语法编写以下内容?
[[a,1],[b,2],[c,3]].map { |r| r[0] }
这给出了参数数量错误的错误。但我不知道在哪里给索引参数。
[[a,1],[b,2],[c,3]].map &:[] # Where to put the index 0 ?
我更喜欢第一种形式,我只是想知道如何使用&:
来实现。
答案 0 :(得分:6)
你做不到。您只能传递没有参数的方法。在您的情况下,您需要将0
作为参数提供,您只能使用块语法。
另一方面,您可以使用first
方法实现相同的目标:
[[a,1],[b,2],[c,3]].map(&:first)
编辑:
Joerg和tokland的答案都激励我进行一些实验。您可以实际执行以下操作:
arr = [[:a, 1], [:b, 2], [:c, 3]]
arr.each_with_object(0).map(&:[])
#=> [:a, :b, :c]
arr.each_with_object(1).map(&:[])
#=> [1, 2, 3]
答案 1 :(得分:3)
Symbol#to_proc
将第一个参数作为接收者,并将它接收的任何额外参数传递给该方法,但在这种情况下,它只传递一个参数,因为Enumerable#map
只传递元素为唯一的论点。
但是,如果那个唯一的参数碰巧是Array
,那么我们可以使用block参数绑定的解构绑定功能!因此,我们可以简单地使用Enumerable#zip
将我们的元素与0
s的无限列表压缩在一起!当然,这要求我们使用具有块参数绑定语义的东西,即块本身:
[[a,1],[b,2],[c,3]].zip([0].cycle).map {|el, i| el[i]}
或非lambda Proc
f = proc {|a, i| a[i] }
[[a,1],[b,2],[c,3]].zip([0].cycle).map(&f)
但是,它确实不适用于Method
或lambdas,因为它们没有块参数绑定语义,它们具有方法参数绑定语义,因此它们不执行自动解构。当然,Symbol#to_proc
会发送一条消息,从而最终调用一个方法而不是一个非lambda Proc
或一个块。这就是为什么这不适用于Symbol#to_proc
。
答案 2 :(得分:0)
简短回答:你不能。
答案很长:
编写自己的智能Array#to_proc
:array.map(&[:[], 0])
。在这种特殊情况下非常难看。
使用构面map_send:
array.map_send(:[], 0)
(和3:正如Mladen所指出的那样:array.map(&:first)
,但如果你想要另一个索引,你就不能这样做了)
答案 3 :(得分:0)
最有可能是矫枉过正,但为了完整起见:你可以编写自己的方法,如
class Array
def to_proc
->(x) { x[first] }
end
end
并像这样使用它:
[[a,1],[b,2],[c,3]].map(&[0])
您可以在我的博文"Array#to_proc for hash access"中了解更多相关信息。