arr = [
{day: 'Monday', class: 1, name: 'X'},
{day: 'Monday', class: 2, name: 'Y'},
{day: 'Tuesday', class: 1, name: 'Z'},
{day: 'Monday', class: 1, name: 'T'}
]
一つの方法は、マージされ、両方のハッシュに存在するキーの値を決定するためにブロックを使用Hash#updateの形を(別名マージ!)を使用することです。ここでは、最初に:day
の値が同じである場合、次にそのようなそれぞれの発生に対して、の値が(同じ値の場合は:day
の場合)2回行われます。
arr.each_with_object({}) { |g,h|
h.update(g[:day]=>{ g[:class].to_s=>[{name: g[:name] }] }) { |_,h1,h2|
h1.update(h2) { |_,p,q| p+q } } }
#=> {"Monday" =>{"1"=>[{:name=>"X"}, {:name=>"T"}], "2"=>[{:name=>"Y"}]},
# "Tuesday"=>{"1"=>[{:name=>"Z"}]}}
手順は次のとおりです。
enum = arr.each_with_object({})
#=> #<Enumerator: [{:day=>"Monday", :class=>1, :name=>"X"},
# {:day=>"Monday", :class=>2, :name=>"Y"},
# {:day=>"Tuesday", :class=>1, :name=>"Z"},
# {:day=>"Monday", :class=>1, :name=>"T"}]:each_with_object({})>
我々は、アレイに変換することによって、この列挙子によって生成される値を見ることができます:
enum.to_a
#=> [[{:day=>"Monday", :class=>1, :name=>"X"}, {}],
# [{:day=>"Monday", :class=>2, :name=>"Y"}, {}],
# [{:day=>"Tuesday", :class=>1, :name=>"Z"}, {}],
# [{:day=>"Monday", :class=>1, :name=>"T"}, {}]]
各アレイ内の空のハッシュが構築され、返されるハッシュです。最初は空ですが、enum
の各要素が処理されると部分的に形成されます。
enum
の最初の要素は(Enumerator#eachによって)ブロックに渡され、ブロック変数が平行割り当て(somtimes 複数割り当てと呼ばれる)を使用して割り当てられている:我々は今、ブロックを実行
g,h = enum.next
#=> [{:day=>"Monday", :class=>1, :name=>"X"}, {}]
g #=> {:day=>"Monday", :class=>1, :name=>"X"}
h #=> {}
を計算:
h.update(g[:day]=>{ g[:class].to_s=>[{name: g[:name] }] })
#=> {}.update("Monday"=>{ "1"=>[{name: "X"}] })
#=> {"Monday"=>{"1"=>[{:name=>"X"}]}}
この操作は、h
の更新された値を返しますハッシュがあること構築された。キー"Monday"
は、(h
は何の鍵を持っていない)ブロック
マージされ、両方のハッシュに存在していなかったので
update
の引数
"Monday"=>{ "1"=>[{name: "X"}] }
が
{ "Monday"=>{ "1"=>[{name: "X"}] } }
の省略形であることを
注意
{ |_,h1,h2| h1.update(h2) { |_,p,q| p+q } } }
は、det "Monday"
の値を決定します。
は今enum
の次の値がブロックに渡され、ブロック変数が割り当てられていますh
が更新されたこと
g,h = enum.next
#=> [{:day=>"Monday", :class=>2, :name=>"Y"},
# {"Monday"=>{"1"=>[{:name=>"X"}]}}]
g #=> {:day=>"Monday", :class=>2, :name=>"Y"}
h #=> {"Monday"=>{"1"=>[{:name=>"X"}]}}
注意を。ブロック計算を実行します。
h.update(g[:day]=>{ g[:class].to_s=>[{name: g[:name] }] })
# {"Monday"=>{"1"=>[{:name=>"X"}]}}.update("Monday"=>{ "2"=>[{name: "Y"}] })
両方のハッシュをマージすると、「月曜日」のキーが共有されます。そこで我々は「月曜日」のマージされた値を決定するためにブロックを使用する必要があります。
{ |k,h1,h2| h1.update(h2) { |m,p,q| p+q } } }
#=> {"1"=>[{:name=>"X"}]}.update("2"=>[{name: "Y"}])
#=> {"1"=>[{:name=>"X"}], "2"=>[{:name=>"Y"}]}
は、k
ブロック変数の説明については、update
のためのドキュメントを参照してくださいh1
とh2
外update
とm
ため、p
とq
内部の場合はupdate
です。 k
およびm
は共通鍵の値です。ブロック計算で使われていないので、私はそれらを一般的な例であるアンダースコアに置き換えました。だから今
:二update
はこのブロックがある
{ |_,p,q| p+q }
ブロックを使用する必要はありませんでしたので、ハッシュh["Monday]
はまだ、キー2
を持っていなかった
h #=> { "Monday" => { "1"=>[{ :name=>"X" }], "2"=>[{ :name=>"Y"}] } }
この操作の前にしかし、enum
の最後の要素がh
にマージされた場合、:day
と:class
の両方の値が2つのha shesがマージされています。
残りの計算は似ています。
あなたは 'groupedArray ['Monday'] => {'1' => [{name: 'X'}、{name: 'T'}]、 '2' => [[ {name: 'Y'}]} '?私はdownvotesのアカウントを期待しています。 –
はい、そうです。申し訳ありませんが間違った角かっこに気付かなかった – Dragos
これを行うためのより短い方法があるかどうかを知りたかっただけです。 – Dragos