2017-05-09 91 views
0

我目前正在尋找合併列表中的元素。這些元素如下所示。代碼是紅寶石合併列表中的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和解析它,但它不工作。

基於下面的答案,我嘗試添加文本字段,但它沒有這樣做它很好

任何想法?

+1

你說的代碼是在Ruby中,但它不是。你能做出適當的Ruby結構嗎? – tadman

回答

0

使用Enumerable#group_by,你可以組集的給定塊的結果:

[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

我想添加一個名爲「字符串」版本的值的文本字段。 – Seb

+0

九月,我按照你的要求添加':text'鍵,但我建議不要那樣做。相反,如果'h'是你構造的散列(沒有鍵':text'),只需根據需要計算'text = h [:value] .join(','))''。原因是,如果你包含一個':text'鍵,每當你改變'h [:value]'時,你都需要更新'h [:text]'。這是效率低下並且是一個令人討厭的bug的潛在來源。這只是不好的編程習慣。 –