Removing duplicate objects from array

2 views
Skip to first unread message

Andrew Sullivan

unread,
Sep 26, 2008, 3:21:59 AM9/26/08
to ur...@googlegroups.com
I've got an array of objects with duplicates that I've got to get rid
of. I've tried using uniq! on the array, but for some reason, it's not
quite working - I'm assuming it has something to do with comparing
objects with one another. Perhaps related, when I try to compare
obvious duplicates using eql?, equal? and == it keeps saying that
these duplicates are not quite the same.

I've come up with the following code that compares the IDs of the
objects (in the array) against one another and removes duplicates, but
this seems very kludgy and inefficient:

def dedupe
(0..@objects.length).each do |i|
if @objects[i]
((i+1)..@objects.length).each do |j|
if @objects[j]
if @objects[i].id == @objects[j].id
@objects[j] = nil
end
end
end
end
end
@objects.compact!
end

I know there's likely an easier and more-efficient way to do this, a
way to hijack uniq! into working with objects, perhaps. Could anyone
enlighten me?

Forgive the awful code, it's been a while since I've done much in Ruby
or read The Ruby Way. This project is meant as a refresher, but I'm
stuck here.

Thanks much,

Andrew

Jordan Curzon

unread,
Sep 26, 2008, 10:07:35 AM9/26/08
to ur...@googlegroups.com
It seems to me that you could redefine === on the class of the object:

class Animal
def ===(obj)
self.id == obj.id
end
end

then uniq! should work I think.

Brian Palmer

unread,
Sep 26, 2008, 10:21:35 AM9/26/08
to ur...@googlegroups.com
uniq works as a hashing function, so if your class doesn't work as a
hash key it's not going to work with uniq either. In other words,
first it checks if a.hash == b.hash and if so, it checks that a.eql?(b).

If you can, just fix the hash and/or eql? methods on the class to work
correctly with your definition of equality. Otherwise something like
your dedupe function is probably your best bet, since hashing isn't
going to work.

-- Brian

Andrew Sullivan

unread,
Sep 26, 2008, 3:28:33 PM9/26/08
to ur...@googlegroups.com
I added hash and eql? methods on the class and uniq! now works (and
seemingly much, much faster than my own function).

Thank you both,

Andrew

grady player

unread,
Sep 26, 2008, 3:30:25 PM9/26/08
to ur...@googlegroups.com
my not very elegant solution would be just make a new array,
and check each time you add an element that the element isn't already in the array.

On Fri, Sep 26, 2008 at 8:21 AM, Brian Palmer <br...@codekitchen.net> wrote:
Reply all
Reply to author
Forward
0 new messages