4

最初我打算做如下的事情:

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]

,这是原始数组,仅被解剖一次。

如何链接两个地图/每个枚举器,以便将枚举器分成 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。如果您想在那之前看到它,您可以使用聊天与我联系,因为我真的很拖延:)

4

5 回答 5

3

也许您需要一个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嵌套结构的第 - 层的 a。

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]]
于 2012-04-14T08:20:08.313 回答
3

听起来像是递归的工作:

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]]
于 2012-04-14T07:20:30.247 回答
2
arr.map {|x| x.map(&:succ)} #=> [[2, 3], [4, 5]]
于 2012-08-14T00:23:19.410 回答
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

于 2012-04-14T05:03:58.977 回答
0

就我个人而言,我只是像下面两个选项之一那样编写它并完成它:

arr.map { |a| a.map(&:next) } 
#=> [[2, 3], [4, 5]]
arr.map { |x, y| [x.next, y.next] } 
#=> [[2, 3], [4, 5]]
于 2012-04-14T10:57:20.267 回答