2012-08-01 56 views
2

鉴于哈希以下数组:如何删除记录,如果它是复制和和值:VAL

list=[ 
    {:cod => "0001", :name => "name1", :val => 10}, 
    {:cod => "0001", :name => "name1", :val => 12}, 
    {:cod => "0002", :name => "name2", :val => 13}, 
    {:cod => "0002", :name => "name2", :val => 14}, 
    {:cod => "0002", :name => "name2", :val => 14}, 
    {:cod => "0004", :name => "name4", :val => 16}, 
    {:cod => "0004", :name => "name4", :val => 16}, 
    {:cod => "0004", :name => "name4", :val => 17}, 
    {:cod => "0005", :name => "name5", :val => 17}, 
    {:cod => "0005", :name => "name5", :val => 17}, 
    {:cod => "0005", :name => "name5", :val => 17}, 
    {:cod => "0006", :name => "name6", :val => 110}, 
    {:cod => "0006", :name => "name6", :val => 10}, 
] 

如何删除重复记录?

此外,我怎样才能找到与键:val的值的总和?

+3

你能澄清这个问题吗?重复的最终总和值:val? – 2012-08-01 14:51:22

+0

这也是一个数组,而不是散列。 – Ultimation 2012-08-01 15:11:12

+0

我们都在回答不同的问题。你是否希望根据具有重复的':val'字段,重复的':cod'-':name'对,或者整个哈希是相同的(或其他)来删除记录? – 2012-08-02 04:42:25

回答

2

您可以将块传递给Array的方法uniq以确定唯一性。

list.uniq { |h| h[:val] } 

=> [{:cod=>"0001", :name=>"name1", :val=>10}, 
{:cod=>"0001", :name=>"name1", :val=>12}, 
{:cod=>"0002", :name=>"name2", :val=>13}, 
{:cod=>"0002", :name=>"name2", :val=>14}, 
{:cod=>"0004", :name=>"name4", :val=>16}, 
{:cod=>"0004", :name=>"name4", :val=>17}, 
{:cod=>"0006", :name=>"name6", :val=>110}] 
1
list.map do |a| 
    list.select { |b| b[:cod] == a[:cod] && b[:name] == a[:name] } \ 
     .reduce { |res, c| {:cod => c[:cod], :name => c[:name], :val => ((res[:val] + c[:val]) || c[:val])} } 
end.uniq { |h| h[:cod]}.each {|c| puts c.inspect} 

输出:

{:name=>"name1", :cod=>"0001", :val=>22} 
{:name=>"name2", :cod=>"0002", :val=>41} 
{:name=>"name4", :cod=>"0004", :val=>49} 
{:name=>"name5", :cod=>"0005", :val=>51} 
{:name=>"name6", :cod=>"0006", :val=>120} 
1

使用GROUP_BY:

list.group_by{|x| x[:cod]}.map{|k, v| v[0].merge({:val => v.map{|x| x[:val]}.reduce(:+)})} 
1

基于答案为止,有什么你实际上是“删除重复的记录意味着一些混乱。 “我对你的意思的解释是你只希望删除完全重复的记录。如果是这样的话,就简单得多比其他的解决方案提出:

list.uniq 

这将返回:

[{:cod=>"0001", :name=>"name1", :val=>10}, 
{:cod=>"0001", :name=>"name1", :val=>12}, 
{:cod=>"0002", :name=>"name2", :val=>13}, 
{:cod=>"0002", :name=>"name2", :val=>14}, 
{:cod=>"0004", :name=>"name4", :val=>16}, 
{:cod=>"0004", :name=>"name4", :val=>17}, 
{:cod=>"0005", :name=>"name5", :val=>17}, 
{:cod=>"0006", :name=>"name6", :val=>110}, 
{:cod=>"0006", :name=>"name6", :val=>10}] 

如果你想的唯一记录:val字段的总和,你可以这样做:

list.uniq.map{|h| h[:val]}.reduce(:+) 

即抓住独特元素(如上所述),然后获取从每个:val值,最后施加:+(加法)来他们得到的总和。

+0

如果真的那么简单,那就太好了!这给出了所有:val的总和,而不是每个唯一的ID。 – pguardiario 2012-08-02 08:55:46

+0

@pguardiario我不确定你的意思。它的确如我所说的那样做:它丢弃重复的“行”(散列,其中':cod',':name'和':val'全部三个相同),然后添加':val'字段依然存在。 – 2012-08-02 16:52:41

1
list.uniq.group_by { |e| [e[:cod], e[:name]] }.map do |k, v| 
    {k => v.map { |h| h[:val] }.reduce(:+)} 
end 

=> [{["0001", "name1"]=>22}, {["0002", "name2"]=>27}, {["0004", "name4"]=>33}, {["0005", "name5"]=>17}, {["0006", "name6"]=>120}]