2017-05-09 90 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的潜在来源。这只是不好的编程习惯。 –