你可以使用Ruby的块简写来调用像数组访问器这样的方法吗?

问题描述 投票:0回答:3

我已经习惯了能够缩短

some_array.map { |e| e.to_s }

some_array.map(&:to_s)

有没有办法缩短

some_array_of_arrays.map { |e| e[4] }

类似于

some_array_of_arrays.map(&:[4])

显然我已经尝试过最后一个例子,但它不起作用。理想情况下,该解决方案将推广到其他“奇怪格式”的方法调用,例如

[]

我对任何 Rails/ActiveSupport 解决方案不感兴趣。仅限普通 Ruby,假设有某种解决方案。

ruby
3个回答
5
投票
你可以使用

Proc

> a = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14]] > third_elem = Proc.new {|x| x[2]} > a.map(&third_elem) #> [3, 7, 11, nil]

> a.map &->(s) {s[2]} #=> [3, 7, 11, nil]
    

4
投票
话又说回来,你可以构建它。它不是那么优雅,但是......

class Call def self.[](name, *args) self.new(name, *args) end def initialize(name, *args) @proc = Proc.new do |obj| obj.send(name, *args) end end def to_proc @proc end end fourth = Call.new(:[], 3) [[1,2,3,4,5],[6,7,8,9,10]].map(&fourth) # => [4, 9] # or equivalently [[1,2,3,4,5],[6,7,8,9,10]].map(&Call.new(:[], 3)) # => [4, 9] [[1,2,3,4,5],[6,7,8,9,10]].map(&Call[:[], 3]) # => [4, 9]

如果你想专门用于索引,你甚至可以简化为:

class Index def self.[](*args) self.new(*args) end def initialize(*args) @proc = Proc.new do |obj| obj[*args] end end def to_proc @proc end end [[1,2,3,4,5],[6,7,8,9,10]].map(&Index[3]) # => [4, 9]

或者,更短,如 @muistooshort 在评论中演示的那样,如果您不想有一个专门的完整课程:

index = ->(*ns) { ->(a) { a[*ns] } } [[1,2,3,4,5],[6,7,8,9,10]].map(&index[3]) # => [4, 9]
    

0
投票
自 Ruby 2.7 起,

最短方式可能会使用“编号块参数”。

some_array_of_arrays.map { _1[4] }
在 Ruby 3.4 中,您应该能够使用 

it

 而不是 
_1
https://bugs.ruby-lang.org/issues/18980

© www.soinside.com 2019 - 2024. All rights reserved.