How to simplify this Enumerator code?

I would like to optimize the following code for brevity.

x1.each { |x| x2.each { |y| .... xN.each { |z| yield {}.merge(x).merge(y)...... merge(z) } } } 

Suppose x1, x2, ..., xN are Enumerator objects.

  • The above is not brief.
  • It works with x1, x2 as Array s, but not as Enumerator s
    • Since enumerator iterators must be reset for inner loops

I tried this, but to no avail:

 [x1, x2, ..., xN].reduce(:product).map { |x| x.reduce :merge } 

Any recommendations?

UPDATE

currently being addressed using

 [x1, x2, ..., xN].map(:to_a).reduce(:product).map { |x| yield x.flatten.reduce(:merge) } 
+6
source share
1 answer

I will start with point 2:

  • At least with the Enumerators I tested ( [{a: 1}, {a: 2}, {a: 3}].each ), your code worked - apparently Enumerator#each rewound at the end or used its own pointer.
  • To do what you want, you need to repeatedly repeat those Enumerator objects (especially internal ones) that with each call to_a will not increase your time complexity (it will remain O(n1*n2*...*nk)

With point # 1, if the call to_a out of the question, you can consider recursion:

 def deep_merge(enum = nil, *enums) if enum.nil? yield({}) else enum.each do |x| deep_merge(*enums) do |h| yield h.merge(x) end end end end 

Now you can call deep_merge(x1, x2, ... xN) and get the desired result ...

+5
source

All Articles