Ruby哈希组合

时间:2014-09-03 20:54:43

标签: ruby-on-rails ruby arrays hash combinations

对于电子商务应用程序,我试图将一个选项的哈希值转换为表示这些选择组合的哈希数组。例如:

# Input:
{ :color => [ "blue", "grey" ],
  :size  => [ "s", "m", "l" ] }

# Output:
[ { :color => "blue", :size => "s" },
  { :color => "blue", :size => "m" },
  { :color => "blue", :size => "m" },
  { :color => "grey", :size => "s" },
  { :color => "grey", :size => "m" },
  { :color => "grey", :size => "m" } ]

输入内部可能有其他选项,每个选项的选项数量不确定,但它只会嵌套1级深度。任何

4 个答案:

答案 0 :(得分:7)

以上的变体:

input = { color: [ "blue", "grey" ],
          size:  [ "s", "m", "l" ],
          wt:    [:light, :heavy] }

keys = input.keys
  #=> [:color, :size, :wt]
values = input.values
  #=> [["blue", "grey"], ["s", "m", "l"], [:light, :heavy]]
values.shift.product(*values).map { |v| Hash[keys.zip(v)] }
  #=> [{:color=>"blue", :size=>"s", :wt=>:light},
  #    {:color=>"blue", :size=>"s", :wt=>:heavy},
  #    {:color=>"blue", :size=>"m", :wt=>:light},
  #    {:color=>"blue", :size=>"m", :wt=>:heavy},
  #    {:color=>"blue", :size=>"l", :wt=>:light},
  #    {:color=>"blue", :size=>"l", :wt=>:heavy},
  #    {:color=>"grey", :size=>"s", :wt=>:light},
  #    {:color=>"grey", :size=>"s", :wt=>:heavy},
  #    {:color=>"grey", :size=>"m", :wt=>:light},
  #    {:color=>"grey", :size=>"m", :wt=>:heavy},
  #    {:color=>"grey", :size=>"l", :wt=>:light},
  #    {:color=>"grey", :size=>"l", :wt=>:heavy}]

答案 1 :(得分:6)

您可以尝试:

ary = input.map {|k,v| [k].product v}
output = ary.shift.product(*ary).map {|a| Hash[a]}

结果:

[
  {:color=>"blue", :size=>"s"},
  {:color=>"blue", :size=>"m"},
  {:color=>"blue", :size=>"l"},
  {:color=>"grey", :size=>"s"},
  {:color=>"grey", :size=>"m"},
  {:color=>"grey", :size=>"l"}
]

答案 2 :(得分:3)

你基本上试图在这里计算组合,这意味着两个级别的迭代,并聚合这些操作的结果:

input = {:color=>["blue", "grey"], :size=>["s", "m", "l"]}

combinations = input[:color].flat_map do |color|
  input[:size].collect do |size|
    { color: color, size: size }
  end
end

puts combinations.inspect
# => [{:color=>"blue", :size=>"s"}, {:color=>"blue", :size=>"m"}, {:color=>"blue", :size=>"l"}, {:color=>"grey", :size=>"s"}, {:color=>"grey", :size=>"m"}, {:color=>"grey", :size=>"l"}]

这里flat_map派上用场,因为它会破坏内部扩张的结果。

答案 3 :(得分:0)

请尝试使用OCG选项组合生成器。

require "ocg"

generator = OCG.new(
  :color => %w[blue grey],
  :size  => %w[s m l]
)

puts generator.next until generator.finished?

Generator包含更多功能,可帮助您处理其他选项。