我正在尝试用ruby中的数据操作。
鉴于此哈希数组
peepz = [
{
:name => 'ted',
:phone => '555-1234',
:color => 'red'
},
{
:name => 'bill',
:phone => '555-2222',
:color => 'green'
},
{
:name => 'ted',
:phone => '555-3333',
:color => 'orange'
},
{
:name => 'dan',
:phone => '555-7777',
:color => 'violet'
},
{
:name => 'ted',
:phone => '555-4444',
:color => 'yellow'
},
{
:name => 'dan',
:phone => '555-6666',
:color => 'orange'
}
];
我希望这个输出
peepz2 = [
{
:name => 'ted'
:phone => ['555-1212','555-3333','555-4444']
:color => ['red','orange','yellow']
},
{
:name => 'bill'
:phone => ['555-2222']
:color => ['green']
},
{
:name => 'dan'
:phone => ['555-7777','555-6666']
:color => ['violet','orange']
},
]
这是我到目前为止所拥有的。
def groupbyer ( peepz, *fields )
peepz.groupby do |peep|
key = ''
fields.each do |field|
key += peep[field].to_s
end
end.each do |group|
????
end
end
groupbyer(peepz, :name)
此方法必须概括。它不能硬编码peepz的字段
完成此任务的红宝石方法是什么?
答案 0 :(得分:4)
peepz
.group_by{|h| h[:name]}.values
.map{|a| a.inject{|h1, h2| h1.merge(h2){|k, v1, v2| k == :name ? v1 : [*v1, v2]}}}
答案 1 :(得分:1)
另一种方法使用Hash#update(aka merge!
)的形式,它使用一个块来确定合并的两个哈希中存在的键的值:
<强>代码强>
def peep_merge(peepz)
peepz.each_with_object({}) { |g,h|
h.update(g[:name]=>(g.merge(g) { |*_,v|
[v] })) { |_,oh,nh| oh.merge(nh) { |_,ov,nv| ov+nv } } }
.values
.each { |h| h[:name] = h[:name].first }
end
示例强>
对于问题中给出的peepz
:
peep_merge(peepz)
#=> [{:name=>"ted",
# :phone=>["555-1234", "555-3333", "555-4444"],
# :color=>["red", "orange", "yellow"]},
# {:name=>"bill",
# :phone=>["555-2222"],
# :color=>["green"]},
# {:name=>"dan",
# :phone=>["555-7777", "555-6666"],
# :color=>["violet", "orange"]}]
<强>解释强>
a = peepz.each_with_object({}) { |g,h|
h.update(g[:name]=>(g.merge(g) { |*_,v|
[v] })) { |_,oh,nh| oh.merge(nh) { |_,ov,nv| ov+nv } } }
#=> {"ted" =>{:name=>["ted", "ted", "ted"],
# :phone=>["555-1234", "555-3333", "555-4444"],
# :color=>["red", "orange", "yellow"]},
# "bill"=>{:name=>["bill"],
# :phone=>["555-2222"],
# :color=>["green"]},
# "dan" =>{:name=>["dan", "dan"],
# :phone=>["555-7777", "555-6666"],
# :color=>["violet", "orange"]}}
b = a.values
#=> [{:name =>["ted", "ted", "ted"],
# :phone=>["555-1234", "555-3333", "555-4444"],
# :color=>["red", "orange", "yellow"]},
# {:name =>["bill"],
# :phone=>["555-2222"],
# :color=>["green"]},
# {:name =>["dan", "dan"],
# :phone=>["555-7777", "555-6666"],
# :color=>["violet", "orange"]}]
最后,要更正:name
键的值:
b.each { |h| h[:name] = h[:name].first }
提供上面示例中显示的结果。