0

我有以下内容:

@array = [['a', 'b'], ['c', 'd'], ['e', 'f', 'g']]

我想创建一个表示上述成员乘积的数组数组@array

我试过这个:

product_array = @array[0].product(@array[1]).product(@array[2])
product_array.map! {|i| i.flatten}

产生:

[["a", "c", "e"],
 ["a", "c", "f"],
 ["a", "c", "g"],
 ["a", "d", "e"],
 ["a", "d", "f"],
 ["a", "d", "g"],
 ["b", "c", "e"],
 ["b", "c", "f"],
 ["b", "c", "g"],
 ["b", "d", "e"],
 ["b", "d", "f"],
 ["b", "d", "g"]]

这就是我想要的答案。

我的问题是:将这个产品方案推广到任何合理长度的@array 的最佳 Ruby 方法是什么?

我正在寻找一个可以工作的单一功能:

@array = [['a', 'b'], ['e', 'f', 'g']]
@array = [['a', 'b'], ['c', 'd'], ['e', 'f', 'g']]
@array = [['a', 'b'], ['c', 'd'], ['e', 'f', 'g'], ['h']]
... many more ...
4

1 回答 1

2

通过示例工作:

array = [['a', 'b'], ['e', 'f', 'g']]
array.first.product(*array[1..-1]).map(&:flatten)
=> [["a", "e"], ["a", "f"], ["a", "g"], ["b", "e"], ["b", "f"], ["b", "g"]]

array = [['a', 'b'], ['c', 'd'], ['e', 'f', 'g']]
array.first.product(*array[1..-1]).map(&:flatten)
=> [["a", "c", "e"], ["a", "c", "f"], ["a", "c", "g"], ["a", "d", "e"], ["a", "d", "f"], ["a", "d", "g"], ["b", "c", "e"], ["b", "c", "f"], ["b", "c", "g"], ["b", "d", "e"], ["b", "d", "f"], ["b", "d", "g"]]

array = [['a', 'b'], ['c', 'd'], ['e', 'f', 'g'], ['h']]
array.first.product(*array[1..-1]).map(&:flatten)
=> [["a", "c", "e", "h"], ["a", "c", "f", "h"], ["a", "c", "g", "h"], ["a", "d", "e", "h"], ["a", "d", "f", "h"], ["a", "d", "g", "h"], ["b", "c", "e", "h"], ["b", "c", "f", "h"], ["b", "c", "g", "h"], ["b", "d", "e", "h"], ["b", "d", "f", "h"], ["b", "d", "g", "h"]]

现在,“展开”product是您想要的方法。以下是文档的相关摘录:

返回所有数组中元素的所有组合的数组。

[1,2].product([3,4],[5,6]) #=> [[1,3,5],[1,3,6],[1,4,5],[1,4,6],
                           #    [2,3,5],[2,3,6],[2,4,5],[2,4,6]]

之前的*运算符*array[1..-1]也称为“splat”,就像踩在数组上并将其内容挤出一样。这与我们将*参数列表中的参数用于方法时相反,它可能应该称为“vacuum”或“hoover”或“suck”,但最后一个保留用于描述我的代码。它的效果在 IRB 中很难看到,因为你不能使用*array,它必须在允许多个数组的地方使用,如product(other_ary, ...). array[1..-1]通常会返回一个数组数组,因此*array[1..-1]导致“数组”而不是原始的“数组数组”。我敢肯定这很令人困惑,但你会明白的。

因此,如果您需要一种方法来做到这一点:

def foo(array)
  array.first.product(*array[1..-1]).map(&:flatten)
end

并戳它:

foo(array)
=> [["a", "c", "e", "h"], ["a", "c", "f", "h"], ["a", "c", "g", "h"], ["a", "d", "e", "h"], ["a", "d", "f", "h"], ["a", "d", "g", "h"], ["b", "c", "e", "h"], ["b", "c", "f", "h"], ["b", "c", "g", "h"], ["b", "d", "e", "h"], ["b", "d", "f", "h"], ["b", "d", "g", "h"]]
于 2013-06-24T23:18:58.803 回答