2014-09-03 307 views
4

對於電子商務應用程序,我試圖將選項的散列(每個選項都包含一系列選項)轉換爲表示這些選項組合的散列數組。例如:紅寶石散列組合

# 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

你可以試試:

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

2

你基本上試圖在這裏計算的組合,這意味着迭代的兩個級別與聚合這些操作的結果的方式:

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

6

以上的變體:

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