红宝石散列组合

问题描述:

对于电子商务应用程序,我试图将选项的散列(每个选项都包含一系列选项)转换为表示这些选项组合的散列数组。例如:红宝石散列组合

# 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级深。任何

你可以试试:

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"} 
] 
+1

我认为你的意思是'shift'而不是'unshift'(如果没有给出任何参数,它不会做任何事情)。而在Ruby 2+中,FWIW可以用'map(&:to_h)',ergo:'ary.shift.product(* ary).map(&:to_h)'替换最后一个'map'。 – 2014-09-03 21:21:06

+0

它看起来像这个解决方案与'shift'工作 – dvanderb 2014-09-03 21:23:02

+0

@Jordan - 当然,我的意思是转变,这是晚了。 :P感谢您指出。 – BroiSatse 2014-09-03 21:23:59

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

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就派上用场了,因为它崩溃的结果的内部扩张。

+0

谢谢。我试图找到一个更一般的方式来做到这一点,不依赖于输入哈希键,因为这些将是用户输入 – dvanderb 2014-09-03 21:02:56

+0

@dvanderb那么也许你应该问这个问题...... – 2014-09-03 21:03:42

+1

@ mu-is-too -short你说得对。同时,当我说“输入内容可能有更多选项,并且每个选项的选项数量不确定时”时,我都认为这是隐含的。我不认为这个解决方案可以很好地处理这种情况。 – dvanderb 2014-09-03 21:06:50

以上的变体:

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}]