Gavin Kistner
3/6/2007 2:27:00 PM
On Mar 6, 7:03 am, senthil <senthilku...@srishtisoft.com> wrote:
> hi all,
> how to remove duplicates of an array of objects based a
> attribute of the object. For ex
> i am having an array of ruby beans named diagnoses . i want
> remove duplicates from the based on the diagnoses id. assume diagnoses
> have attributes id and weightage .So for two diagnoses with same id and
> different weightage , the diagnoses with lower weightage should be
> removed.
Here's my best shot at it:
require 'set'
class Array
def uniq_by
seen = Set.new
select{ |x| seen.add?( yield( x ) ) }
end
end
a = [ {:a=>1, :d=>1}, {:b=>2}, {:c=>3}, {:a=>1, :d=>3} ]
p a, a.uniq, a.uniq_by{ |h| h[:a] }
#=> [{:a=>1, :d=>1}, {:b=>2}, {:c=>3}, {:a=>1, :d=>3}]
#=> [{:a=>1, :d=>1}, {:b=>2}, {:c=>3}, {:a=>1, :d=>3}]
#=> [{:a=>1, :d=>1}, {:b=>2}]
(Note how :b=>2 and :c=>3 have the same value for :a (nil), so only
one is included.)
Here's another (assumedly slower) version that doesn't rely on Set:
class Array
def uniq_by
seen = {}
select{ |x|
v = yield(x)
!seen[v] && (seen[v]=true)
}
end
end