如何使用子数组中的值创建数组的乘积

时间:2013-06-24 22:58:29

标签: ruby

我有以下内容:

@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 ...

1 个答案:

答案 0 :(得分: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"]]

现在,为了'splode,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"]]