2

foldこの問題に対する適切な (または map、reduce などの) スタイルの解決策があるかどうか疑問に思っています。

購入のコレクション (order_items) を提供します。各製品/SKU の合計を収集したいと考えています。

コレクションの例:

[{sku: "A", price:10}, 
 {sku: "B", price:5}, 
 {sku: "C", price:2}, 
 {sku: "B", price:5}, 
 {sku: "A", price:10}, 
 {sku: "B", price:5}]

そして、次の結果を取得します。

{"A":20, "B":15, "C":2} 

現在、私は次のようにしています:

aggregate = order_items.each_with_object({}){|i,o|
  o[i[:sku]] ||= 0
  o[i[:sku]] += i[:price]
}

これは私が望むものを私に与えますが、これを行うためのよりエレガントな方法があるかどうか知りたいですか?

明らかに、単一の SKU に事前にフィルター処理すると、従来のreduceie を実行できます。

# assuming sku is a flat array of values for a single sku type...
aggregate_sku = sku.reduce(:+)

ただし、元のコレクションを事前にフィルター処理する必要はありません。これを達成する方法はありますか、それともすでに可能な限りのことをしていますか?

どんな助けでも大歓迎です。

質問を明確にするために編集されました。締めくくりに投票する必要がある場合は、まずコメントを投稿してください。明確にすることができます。

サブテキスト: などに機能 (またはより可能性の高い手法) があるかどうかmapreduceわかりません。まだ理解していません。ありがとうございます。

4

3 に答える 3

2
order_items = [
 {sku: "A", price:10}, 
 {sku: "B", price:5}, 
 {sku: "C", price:2}, 
 {sku: "B", price:5}, 
 {sku: "A", price:10}, 
 {sku: "B", price:5}
]

aggregate = order_items.each_with_object(Hash.new(0)) do |item, acc|
  acc[ item[:sku] ] += item[:price]
end

--output:--
{"A"=>20, "B"=>15, "C"=>2}
于 2013-07-26T06:59:13.310 に答える
1
order_items.inject(Hash.new) {|hash, item| hash[item[:sku]] = (hash[item[:sku]] || 0) + item[:price]; hash}

集計では大文字と小文字injectの代わりに使用しeach_with_object、簡略化します。nilしかし、それはあなたの質問とほぼ同じです。


@7stud の回答をご覧ください。彼は0デフォルト値をより適切に処理しています。

于 2013-07-26T05:12:04.943 に答える
1

Enumerable#group_by の使用

agg = order_items.group_by { |item| item.sku }
agg.each { |sku, items| agg[sku] = items.map(&:price).reduce(:+) }
于 2013-07-26T05:03:02.480 に答える