How do I get the unique elements from an array of hashes in Ruby? How do I get the unique elements from an array of hashes in Ruby? arrays arrays

How do I get the unique elements from an array of hashes in Ruby?


I can get what I want by calling inject

a = [{:a => 1},{:a => 2}, {:a => 1}]a.inject([]) { |result,h| result << h unless result.include?(h); result }

This will return:

[{:a=>1}, {:a=>2}]


Ruby 1.8.7+ will return just what you have expected:

[{:a=>1}, {:a=>2}, {:a=>1}].uniq#=> [{:a=>1}, {:a=>2}] 


I've had a similar situation, but hashes had keys. I used sorting method.

What I mean:

you have an array:

[{:x=>1},{:x=>2},{:x=>3},{:x=>2},{:x=>1}]

you sort it (#sort_by {|t| t[:x]}) and get this:

[{:x=>1}, {:x=>1}, {:x=>2}, {:x=>2}, {:x=>3}]

now a bit modified version of answer by Aaaron Hinni:

your_array.inject([]) do |result,item|   result << item if !result.last||result.last[:x]!=item[:x]  resultend

I've also tried:

test.inject([]) {|r,h| r<<h unless r.find {|t| t[:x]==h[:x]}; r}.sort_by {|t| t[:x]}

but it's very slow. here is my benchmark:

test=[]1000.times {test<<{:x=>rand}}Benchmark.bmbm do |bm|  bm.report("sorting: ") do    test.sort_by {|t| t[:x]}.inject([]) {|r,h| r<<h if !r.last||r.last[:x]!=h[:x]; r}  end  bm.report("inject: ") {test.inject([]) {|r,h| r<<h unless r.find {|t| t[:x]==h[:x]}; r}.sort_by {|t| t[:x]} }end

results:

Rehearsal ---------------------------------------------sorting:    0.010000   0.000000   0.010000 (  0.005633)inject:     0.470000   0.140000   0.610000 (  0.621973)------------------------------------ total: 0.620000sec                user     system      total        realsorting:    0.010000   0.000000   0.010000 (  0.003839)inject:     0.480000   0.130000   0.610000 (  0.612438)