假设我有以下哈希数组:
[
{:first_name => "john", :last_name => "doe", :items_purchased => 1, :price => 5},
{:first_name => "john", :last_name => "doe", :items_purchased => 4, :price => 20},
{:first_name => "john", :last_name => "doe", :items_purchased => 4, :price => 20},
{:first_name => "jane", :last_name => "doe", :items_purchased => 2, :price => 7},
{:first_name => "jane", :last_name => "doe", :items_purchased => 3, :price => 14},
{:first_name => "test", :last_name => "user", :items_purchased => 1, :price => 4}
]
我想根据某些属性进行重复数据删除(本例中为first_name
和last_name
),然后将items_purchased
和price
一起添加以接收以下输出
[
{:first_name => "john", :last_name => "doe", :items_purchased => 9, :price => 45},
{:first_name => "jane", :last_name => "doe", :items_purchased =>5, :price => 21},
{:first_name => "test", :last_name => "user", :items_purchased => 1, :price => 4}
]
有没有一种简单的方法可以在rails中完成此操作?我一直在用group_by
和merge
方法纠结我的想法,需要一些帮助。
由于
答案 0 :(得分:1)
还有一种皮肤猫的方法:
x = [
{:first_name => "john", :last_name => "doe", :items_purchased => 1, :price => 5},
{:first_name => "john", :last_name => "doe", :items_purchased => 4, :price => 20},
{:first_name => "john", :last_name => "doe", :items_purchased => 4, :price => 20},
{:first_name => "jane", :last_name => "doe", :items_purchased => 2, :price => 7},
{:first_name => "jane", :last_name => "doe", :items_purchased => 3, :price => 14},
{:first_name => "test", :last_name => "user", :items_purchased => 1, :price => 4}
]
group_keys = [:first_name,:last_name]
x.group_by{|h| h.values_at(*group_keys)}.map do |_,a|
a.reduce do |memo,obj|
memo.merge(obj){|k,v1,v2| group_keys.include?(k) ? v1 : v1 + v2}
end
end
首先我们group_by
使用相应的键,然后使用Enumerable#reduce
既然您说过rails,如果您可以解释这些数据的来源,那么可能有一种更简单的数据库方式来处理这个问题。
答案 1 :(得分:0)
这似乎是一个复杂的解决方案。也许其他人可以提出更简单的事情:
IntegerField
如果您不在乎结果与我的结果完全相同:
x = [
{:first_name => "john", :last_name => "doe", :items_purchased => 1, :price => 5},
{:first_name => "john", :last_name => "doe", :items_purchased => 4, :price => 20},
{:first_name => "john", :last_name => "doe", :items_purchased => 4, :price => 20},
{:first_name => "jane", :last_name => "doe", :items_purchased => 2, :price => 7},
{:first_name => "jane", :last_name => "doe", :items_purchased => 3, :price => 14},
{:first_name => "test", :last_name => "user", :items_purchased => 1, :price => 4}
]
# Set the keys to group on:
group_keys = [:first_name,:last_name]
# For each group:
result = x.group_by{|x| x.values_at(*group_keys)}.map do |k,v|
# Create a hash:
result_hash = Hash.new
# For the group keys just add the vaules of the group by
group_keys.zip(k).each{|x,y| result_hash[x] = y }
# For the rest of the keys just add up the vaulus using inject:
(v.first.keys-group_keys).each{|key| result_hash[key] = v.map{|x| x[key]}.inject(:+) }
#return result_hash
result_hash
end
p result #=> [{:first_name=>"john", :last_name=>"doe", :items_purchased=>9, :price=>45}, {:first_name=>"jane", :last_name=>"doe", :items_purchased=>5, :price=>21}, {:first_name=>"test", :last_name=>"user", :items_purchased=>1, :price=>4}]
答案 2 :(得分:0)
您可以将group_by
与一个块一起使用全名分组:
grouped_data = data.group_by { |u| "#{u[:first_name]} #{u[:last_name]}" }
然后你可以遍历每个值,用reduce
来总结你想要的任何东西:
grouped_data.map do |full_name, entries|
entries.reduce(Hash.new(0)) do |output, entry|
output[:items_purchased] += entry[:items_purchased]
output[:price] += entry[:price]
output
end.merge(entries.first.slice(:first_name, :last_name))
end
将输出您想要的数据:
[
{:items_purchased=>9, :price=>45, :first_name=>"john", :last_name=>"doe"},
{:items_purchased=>5, :price=>21, :first_name=>"jane", :last_name=>"doe"},
{:items_purchased=>1, :price=>4, :first_name=>"test", :last_name=>"user"}
]