6

为了简洁起见,我想优化以下代码。

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

假设x1, x2, ..., xNEnumerator对象。

  1. 以上不简洁
  2. 它适用于 x1, x2 作为Arrays,但不适用于Enumerators
    • 因为应该为内部循环重置枚举器迭代器

我试过这个但没有成功:

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

有什么建议吗?

更新

目前解决了:

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

1 回答 1

5

我将从第 2 点开始:

  • 至少在Enumerators我测试过 ( [{a: 1}, {a: 2}, {a: 3}].each) 的情况下,您的代码可以正常工作 - 显然Enumerator#each要么在最后倒带,要么它使用自己的指针。
  • 为了做你想做的事,你需要对对象(尤其是内部对象)进行多次迭代,Enumerator以至于一开始调用to_a每个对象都不会增加你的时间复杂度(它会保持O(n1*n2*...*nk)

对于第 1 点,如果调用to_a是不可能的,您可以考虑递归:

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

现在您可以致电deep_merge(x1, x2, ... xN)并获得所需的结果...

于 2014-05-07T14:12:14.627 回答