如何使用Ruby的Symbol#to_proc访问数组中的数组?

时间:2011-04-18 10:46:33

标签: ruby

如何使用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 ?

我更喜欢第一种形式,我只是想知道如何使用&:来实现。

4 个答案:

答案 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)

简短回答:你不能。

答案很长:

  1. 编写自己的智能Array#to_procarray.map(&[:[], 0])。在这种特殊情况下非常难看。

  2. 使用构面map_send

  3. 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"中了解更多相关信息。