Ruby: Enumerator Chain

At first, I was going to do something like below:

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

p new_arr

Conclusion:

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

But then I tried to shorten it by “linking” the counters:

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

Then he gives an error to_ary method missing

I debugged it

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

Conclusion:

[1,2]
[3,4]

which is the original array and only opens once.

How can I link two cards / each counter so that it lists at 2 (or more) levels? Or should he be in a block?


Update:

, -, 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 . , , , :)

+3
5

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

a 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]]
+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]]
+2
arr.map {|x| x.map(&:succ)} #=> [[2, 3], [4, 5]]
+1
source

To do this, writing x+1only once, you need to put it in a block. Otherwise, you can:

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

Or, if you insist, you can do:

new_arr = arr.flatten (1) .map {| x | x + 1} .each_slice (2) .to_a

0
source

Personally, I will simply write it as one of the two options below and do it with it:

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

All Articles