2017-05-09 18 views
0

現在、リストから要素をマージしようとしています。これらの要素は、次のようにハッシュになります。コードはRubyにありますリストからjson要素をマージする

[ 
{ 
    :id => 0, 
    :value => ["titi"], 
    :allow => true, 
    :text => "titi" 
}, 
{ 
    :id => 0, 
    :value => ["tata"], 
    :allow => true 
    :text => "tata" 
}, 
{ 
    :id => 1, 
    :value => ["blabla"], 
    :allow => true, 
    :text => "blabla" 
}, 
{ 
    :id => 2, 
    :value => ["ok"], 
    :allow => true, 
    :text => "ok" 
}, 
{ 
    :id => 2, 
    :value => ["ko"], 
    :allow => true, 
    :text => "ko" 
} 
] 

私の目標は、同じ「id」に基づいてフィールド値をマージすることです。

[ 
{ 
    :id => 0, 
    :value => ["titi", "tata"], 
    :allow => true, 
    :text => "titi, tata" 
}, 
{ 
    :id => 1, 
    :value => ["blabla"], 
    :allow => true 
    :text => "blabla" 
}, 
{ 
    :id => 2, 
    :value => ["ok", "ko"], 
    :allow => true, 
    :text => "ok, ko" 
} 
] 

私はlist.mapを使用しようとしましたが、解析しても機能しません。下の回答に基づいて

は、私は、テキストフィールドを追加しようとしましたが、それはうまく

任意のアイデアを、それを行うことができませんでしたか? Enumerable#group_byを使用して

+1

あなたはコードがRubyであると言うが、そうではありません。それを適切なRuby構造にすることはできますか? – tadman

答えて

0

、あなたは、与えられたブロックの結果により、グループコレクションすることができます:グループ化されたコレクションを組み合わせることにより

[1, 2, -1, 3, -3].group_by { |i| i.abs } 
# => {1=>[1, -1], 2=>[2], 3=>[3, -3]} 
[1, 2, -1, 3, -3].group_by { |i| i.abs }.values 
# => [[1, -1], [2], [3, -3]] 

、あなたがこれを行うの

ary = [ 
    { id: 0, value: ["titi"], allow: true }, 
    { id: 0, value: ["tata"], allow: true }, 
    { id: 1, value: ["blabla"], allow: true }, 
    { id: 2, value: ["ok"],  allow: true }, 
    { id: 2, value: ["ko"],  allow: true } 
] 

ary.group_by { |h| h[:id] }.values.map { |hs| 
    hs.inject { |h1, h2| 
    # h1 = h1.clone # to preserve original hash (in ary) 
    h1[:value] += h2[:value] 
    h1 

    # OR 
    # h1.merge(h2) { |key, oldval, newval| 
    # key == :value ? oldval + newval : oldval 
    # } 
    } 
} 

# => [{:id=>0, :value=>["titi", "tata"], :allow=>true}, 
#  {:id=>1, :value=>["blabla"], :allow=>true}, 
#  {:id=>2, :value=>["ok", "ko"], :allow=>true}] 
0

一つの方法は、使用することです欲しいものを得るでしょうブロックを使用して両方のハッシュがマージされているキーの値を決定する形式のHash#update(別名merge!)です。

arr = [ 
    { id: 0, value: ["titi"], allow: true }, 
    { id: 0, value: ["tata"], allow: true }, 
    { id: 1, value: ["blabla"], allow: true }, 
    { id: 2, value: ["ok"],  allow: true }, 
    { id: 2, value: ["ko"],  allow: true } 
] 

arr.each_with_object({}) { |g,h| 
    h.update(g[:id]=>g) { |_k,o,n| o.merge(value: o[:value]+n[:value]) } }. 
    values. 
    map { |g| g.merge(text: g[:value].join(', ')) } 
    #=> [{:id=>0, :value=>["titi", "tata"], :allow=>true, :text=>"titi, tata"}, 
    # {:id=>1, :value=>["blabla"], :allow=>true, :text=>"blabla"}, 
    # {:id=>2, :value=>["ok", "ko"], :allow=>true, :text=>"ok, ko"}] 

私はブロック変数_konの説明についてはドキュメントを参照してください 。 _kの(オプションの)アンダースコアは、そのブロック変数がブロック計算で使用されていないことを示します。 values

は、ハッシュ値を抽出するために最後に使用され、私たちは次のように計算しています

arr.each_with_object({}) { |g,h| 
    h.update(g[:id]=>g) { |_k,o,n| o.merge(value: o[:value]+n[:value]) } } 
    #=> {0=>{:id=>0, :value=>["titi", "tata"], :allow=>true}, 
    # 1=>{:id=>1, :value=>["blabla"], :allow=>true}, 
    # 2=>{:id=>2, :value=>["ok", "ko"], :allow=>true}} 
+0

私は値の "文字列"バージョンのtextというフィールドを追加したいと思います。 – Seb

+0

9月、私はあなたが要求した通りに ':text'キーを追加しますが、それに反対することをお勧めします。むしろ、 'h 'があなたが構築するハッシュ(キー':text'なし)なら、必要に応じて 'text = h [:value] .join('、 '))'を計算するだけです。その理由は、 ':text'キーをインクルードすると' h [:value] 'を変更するたびに' h [:text] 'を更新する必要があるからです。それは非効率的であり、厄介なバグの潜在的な原因です。それは良いプログラミングの練習ではありません。 –

関連する問題