2012-04-14 86 views
3

起初,我打算做类似如下:红宝石:枚举链

arr = [[1,2],[3,4]] 
new_arr = 
arr.map do |sub_arr| 
    sub_arr.map do |x| 
     x+1 
    end 
end 

p new_arr 

输出:

[[2,3],[4,5]] 

但后来我试图总之,它通过“链接起来”普查员:

arr.map.map{|x| x+1} 

然后它给出错误to_ary method missing

我调试它由

arr.each.each{|x| p x} 

输出:

[1,2] 
[3,4] 

,它是原始阵列和仅desected一次。

我该如何链接两个地图/每个枚举员,以便它将枚举器分为2个(或更多)级别?或者它必须在块?


更新:

经过一番搜索,显然链obj.Enumerator.Enumerator.Enumerator...只列举了OBJ一次,而且只有1米的深度。为了更深入,块是必需的。我制定了简单的代码,将字符串转换为块(Proc/Lambda;类似于符号到块但更多的使用;更像是一个函数式语法),这样就可以避免块。有人有类似的代码String#to_proc,但我找不到它,而x,y这件事并不符合我的口味。我用$0,$1,$2,...

示例代码(在前面的例子可以写成):

arr = [[1,2],[3,4]] 
new_arr = arr.map(&'[$0+1,$1+1]') 
p new_arr 

我将推动原代码以后github上。你可以使用聊天联系我,如果你想在此之前看到它,因为我真的拖延:)

回答

2

也许你需要一个map你想申请只在叶子:

module Enumerable 
    def nested_map &block 
    map{|e| 
     case e 
     when Enumerable 
     e.nested_map(&block) 
     else 
     block.call(e) 
     end 
    } 
    end 
end 

p [[1,2], [3,4]].nested_map(&:succ) 
#=> [[2, 3], [4, 5]] 

map将适用仅在嵌套结构的第n层级上。

module Enumerable 
    def deep_map level, &block 
    if level == 0 
     map(&block) 
    else 
     map{|e| e.deep_map(level - 1, &block)} 
    end 
    end 
end 

p [[1,2], [3,4]].deep_map(1, &:succ) 
#=> [[2, 3], [4, 5]] 
0

为了做到这一点只写一次x+1,你需要把它放在一个块。否则,你可以这样做:

new_arr = arr.map {| x,y | [X + 1,Y + 1]}

或者,如果坚持,可以这样做:

new_arr = arr.flatten(1).MAP {| X | X + 1} .each_slice(2)。to_a

2

听起来像是递归工作:

def zipper(args) 
    args[0].respond_to?(:each) ? args.map{|a| zipper(a)} : args.map{|i| i+1} 
end 

zipper([[1,2],[3,4]]) 
# => [[2, 3], [4, 5]] 

zipper([[[1,2],[3,4]],[5,6]]) 
# => [[[2, 3], [4, 5]], [6, 7]] 
0

个人而言,我只是会写它像的下面两个选项中的一个,并用它做:

arr.map { |a| a.map(&:next) } 
#=> [[2, 3], [4, 5]] 
arr.map { |x, y| [x.next, y.next] } 
#=> [[2, 3], [4, 5]] 
1
arr.map {|x| x.map(&:succ)} #=> [[2, 3], [4, 5]]