【问题标题】:Ruby: Enumerator ChainRuby:枚举器链
【发布时间】:2013-05-02 11:50:49
【问题描述】:

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

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]

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

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

【问题讨论】:

    标签: ruby enumerable


    【解决方案1】:

    也许您需要一个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-th 级别。

    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]]
    

    【讨论】:

      【解决方案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]]
      

      【讨论】:

        【解决方案3】:
        arr.map {|x| x.map(&:succ)} #=> [[2, 3], [4, 5]]
        

        【讨论】:

          【解决方案4】:

          为了通过只写一次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

          【讨论】:

            【解决方案5】:

            就我个人而言,我只是将它写成以下两个选项之一并完成它:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-11-01
              • 2012-11-07
              • 2016-12-24
              • 2017-10-07
              • 2012-05-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多