嵌套数组并生成类似真值表的组合

时间:2016-03-25 05:40:12

标签: ruby-on-rails arrays ruby

我有一个这样的嵌套数组:

levels = [["d11", "d12"],["d21", "d22"],["d31", "d32"],["d41", "d42"]]

我需要生成类似真值表的东西。我需要一组由不同子数组的组合填充的数组,如下所示:

levels =  [["d11", "d21", "d31", "d41"],
           ["d11", "d21", "d31", "d42"],
           ["d11", "d21", "d32", "d41"],
           ["d11", "d21", "d32", "d42"],
           ["d11", "d22", "d31", "d41"],
           ["d11", "d22", "d31", "d42"]]

等等,直到最后一个。总共会有16种组合。

我嵌套了每个方法迭代子数组,但没有得到预期的输出。

<% levels.each do |p| %>
 <% p.each do |c| %>
  <p> <%= c %></p>
 <% end %>
<% end %>

我正在关注this,这是我想要的,但我没有分离的数组,我把它们都放在一个大数组中,我不知道如何复制他的迭代在我的多维数组中的两个单独的数组。

我希望有人能帮助我。

3 个答案:

答案 0 :(得分:2)

levels.first.product(*levels.drop(1))

first, *rest = levels
first.product(*rest)

输出:

[
  ["d11", "d21", "d31", "d41"],
  ["d11", "d21", "d31", "d42"],
  ["d11", "d21", "d32", "d41"],
  ["d11", "d21", "d32", "d42"],
  ["d11", "d22", "d31", "d41"],
  ["d11", "d22", "d31", "d42"],
  ["d11", "d22", "d32", "d41"],
  ["d11", "d22", "d32", "d42"],
  ["d12", "d21", "d31", "d41"],
  ["d12", "d21", "d31", "d42"],
  ["d12", "d21", "d32", "d41"],
  ["d12", "d21", "d32", "d42"],
  ["d12", "d22", "d31", "d41"],
  ["d12", "d22", "d31", "d42"],
  ["d12", "d22", "d32", "d41"],
  ["d12", "d22", "d32", "d42"]
]

答案 1 :(得分:1)

您正在寻找的内容称为cartesian product,可以这样计算:

>> levels.inject(&:product).map(&:flatten)
=> [["d11", "d21", "d31", "d41"], ["d11", "d21", "d31", "d42"], ["d11", "d21", "d32", "d41"], ["d11", "d21", "d32", "d42"], ["d11", "d22", "d31", "d41"], ["d11", "d22", "d31", "d42"], ["d11", "d22", "d32", "d41"], ["d11", "d22", "d32", "d42"], ["d12", "d21", "d31", "d41"], ["d12", "d21", "d31", "d42"], ["d12", "d21", "d32", "d41"], ["d12", "d21", "d32", "d42"], ["d12", "d22", "d31", "d41"], ["d12", "d22", "d31", "d42"], ["d12", "d22", "d32", "d41"], ["d12", "d22", "d32", "d42"]]

虽然我敢打赌,这样的计算可能应该在控制器或模型中完成,而不是在视图中完成。

答案 2 :(得分:0)

当然应该在这里使用

Array#product,但是(为了说明)可以改为使用递归。

def cartesian(arr)
  return arr.first.map { |e| [e] } if arr.size == 1
  first, *rest = arr
  first.each_with_object([]) { |e,arr| cartesian(rest).each { |a| arr << [e, *a] } }
end

cartesian(levels)
  #=> [["d11", "d21", "d31", "d41"],
  #    ["d11", "d21", "d31", "d42"],
  #   ...
  #    ["d12", "d22", "d32", "d42"]] 

cartesian(levels).size
  #=> 16