Initially 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
Output:
[[2,3],[4,5]]
But then I tried to short it by "chaining up" the enumerators:
arr.map.map{|x| x+1}
Then it gives error to_ary method missing
I debugged it by
arr.each.each{|x| p x}
Output:
[1,2]
[3,4]
,which is the original array and only desected once.
How can I chain two map/each enumerators so it will enumerator into 2 (or more) levels? Or it has to be in the block?
Update:
After some searching, apparently a chain obj.Enumerator.Enumerator.Enumerator...
only enumerates the obj once, and only 1 level depth. In order to go deeper, block is required. I worked out simple code that would convert string to block(Proc/Lambda; similar to symbol to block but more of use; more like a functional syntax) so that block will be avoided. Someone has similar code String#to_proc
but I couldn't find it, and the x,y
thing in it does not appeal to my taste. I use $0,$1,$2,...
Sample code (the previous example will be written as):
arr = [[1,2],[3,4]]
new_arr = arr.map(&'[$0+1,$1+1]')
p new_arr
I will push the original code to github later. You can use chat to contact me if you want to see it before that because I really procrastinate :)
Perhaps you need a map
which you would like to apply only on the leafs:
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]]
or a map
which would apply only on n
-th level of the nested structure.
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]]
Sounds like a job for recursion:
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]]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With