Marco
Marco

Reputation: 4395

How to remove duplicates from array of hashes based on keys only?

How would you go about removing duplicates based on the key?

values = [{"a"=>"1"}, {"a"=>"2"}, {"b"=>"1"}, {"a"=>"4"}]

How can I ignore the value and run uniq based on key so that it returns:

[{'a' => '1'}, {'b' => '1'}]

Upvotes: 1

Views: 2939

Answers (3)

Wes
Wes

Reputation: 6585

Without introducing any intermediate variables the following 1 liner will do the trick:

> [{"a"=>"1"}, {"a"=>"2"}, {"b"=>"1"}, {"a"=>"4"}].inject({}) {|s,h| s.merge(h) unless s.keys.include? h.keys}.inject([]) {|s,h| s << {h[0]=>h[1]}}
 => [{"a"=>"4"}, {"b"=>"1"}]

Upvotes: 0

sawa
sawa

Reputation: 168101

The following will work only in ruby 1.9, so it might be useless.

Hash[values.map(&:first).reverse].map{|a| Hash[*a]}

If you need it in the original order,

values & Hash[values.map(&:first).reverse].map{|a| Hash[*a]}

Upvotes: 2

Robert Brown
Robert Brown

Reputation: 11016

Assuming you don't care which value gets clobbered, just run them into a hash (which does have unique keys and is therefore probably the right collection class for this case):

h = {}
values.each{|i|i.each{|k,v|h[k] = v}}
puts h # => {"a"=>"4", "b"=>"1"}

... or if you want the first of each key:

h = {}
values.each{|i|i.each{|k,v|h[k] = v unless h[k]}}

If you want to get back to a Array:

h.each{|k,v|a << {k=>v}}

Upvotes: 5

Related Questions