编辑:我刚刚意识到我之前的例子很糟糕。
借用@ZachKemp的想法(并改变它):
class Object
def eval_multi(*methods)
#methods.inject(self) { |memo, m| memo.send(m) }
methods.inject(self) { |memo, m| eval("#{memo}.#{m}") }
end
end
[1,2,3].eval_multi("product([4,5,6])", :transpose)
=> [[1, 1, 1, 2, 2, 2, 3, 3, 3], [4, 5, 6, 4, 5, 6, 4, 5, 6]]
我想知道是否有一种内置的方法可以做到这一点,而无需编写上面的eval_multi
方法。
您可以使用
inject
执行此操作:
module Enumerable
def multimap(*methods)
methods.inject(self){|result, method| result.map(&method) }
end
end
arr = ["1 a", "1 b", "2 c", "2 a"]
arr.multimap(:split, :reverse, :join)
#=> ["a1", "b1", "c2", "a2"]
(我重命名了该方法,因为它在 Ruby 中已经eval
了另一个含义)。
你可以只使用一张地图,简单而干净。
arr.map{ |o| o.split.reverse.join }
您可以通过稍微改变传递参数的方式来做到这一点。
[[:product, [4,5,6]], [:transpose]].inject([1,2,3]){|m, a| m.send(*a)}
# => [[1, 1, 1, 2, 2, 2, 3, 3, 3], [4, 5, 6, 4, 5, 6, 4, 5, 6]]
或者,通过稍微修改一下send
,您可以像这样做:
class Object
def send_splat a; send(*a) end
end
[[:product, [4,5,6]], [:transpose]].inject([1,2,3], &:send_splat)
# => [[1, 1, 1, 2, 2, 2, 3, 3, 3], [4, 5, 6, 4, 5, 6, 4, 5, 6]]