# Getting an array of unique objects of a class i wrote

**URL:** <https://rubytalk.org/t/getting-an-array-of-unique-objects-of-a-class-i-wrote/49076>\
**Category:** ruby-talk\
**Created:** [14 September 2008 11:08 UTC](https://rubytalk.org/t/getting-an-array-of-unique-objects-of-a-class-i-wrote/49076 "2008-09-14T11:08:09Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Adam\_Akhtar](https://avatars.discourse-cdn.com/v4/letter/a/c89c15/32.png) [@Adam\_Akhtar](https://rubytalk.org/u/Adam_Akhtar)\
**Post date:** [14 September 2008 11:08 UTC](https://rubytalk.org/t/getting-an-array-of-unique-objects-of-a-class-i-wrote/49076/1 "2008-09-14T11:08:09Z")

</div>

Hi Ive done some searching on this but couldnt find an answer that was  
either totally appropriate or one that i could understand ;\> (some  
advanced stuff going on).

So if i have a class with two variables (strings) like this

class thing  
attr\_accessor :name :job  
end

and i want to ensure that if i have an array of these objects there will  
be no duplicates. A duplicate would be where both the name and job are  
the same in both objects.

I tried using uniq! but it didnt work. Not sure why (can someone explain  
that).

Ive heard of set, could that be used in this case to prevent duplicates  
being added?

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Lex\_Williams](https://avatars.discourse-cdn.com/v4/letter/l/e5b9ba/32.png) [@Lex\_Williams](https://rubytalk.org/u/Lex_Williams)\
**Post date:** [14 September 2008 11:14 UTC](https://rubytalk.org/t/getting-an-array-of-unique-objects-of-a-class-i-wrote/49076/2 "2008-09-14T11:14:41Z")

</div>

use a hash

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Michael\_Guterl1](https://avatars.discourse-cdn.com/v4/letter/m/e47c2d/32.png) [@Michael\_Guterl1](https://rubytalk.org/u/Michael_Guterl1)\
**Post date:** [14 September 2008 11:21 UTC](https://rubytalk.org/t/getting-an-array-of-unique-objects-of-a-class-i-wrote/49076/3 "2008-09-14T11:21:37Z")

</div>

You need to implement Thing#eql? and Thing#hash in order for a  
Array#uniq, Set, or Hash to function as you expect.

> **···**
>
> On Sun, Sep 14, 2008 at 7:08 AM, Adam Akhtar \<adamtemporary@gmail.com\> wrote:
> 
> > Hi Ive done some searching on this but couldnt find an answer that was  
> > either totally appropriate or one that i could understand ;\> (some  
> > advanced stuff going on).
> > 
> > So if i have a class with two variables (strings) like this
> > 
> > class thing  
> > attr\_accessor :name :job  
> > end
> > 
> > and i want to ensure that if i have an array of these objects there will  
> > be no duplicates. A duplicate would be where both the name and job are  
> > the same in both objects.
> > 
> > I tried using uniq! but it didnt work. Not sure why (can someone explain  
> > that).
> > 
> > Ive heard of set, could that be used in this case to prevent duplicates  
> > being added?

---

<div class="post-metadata">

**Author:** ![Sebastian\_Hungereck1](https://avatars.discourse-cdn.com/v4/letter/s/3ab097/32.png) [@Sebastian\_Hungereck1](https://rubytalk.org/u/Sebastian_Hungereck1)\
**Post date:** [14 September 2008 11:29 UTC](https://rubytalk.org/t/getting-an-array-of-unique-objects-of-a-class-i-wrote/49076/4 "2008-09-14T11:29:37Z")

</div>

Adam Akhtar wrote:

> class thing  
> attr\_accessor :name :job  
> end

Thing = Struct.new(:name, :job)

> and i want to ensure that if i have an array of these objects there will  
> be no duplicates. A duplicate would be where both the name and job are  
> the same in both objects.
> 
> I tried using uniq! but it didnt work. Not sure why (can someone explain  
> that).

For uniq to work your class has to implement hash and eql?, so that for any  
two objects that you consider equal o1.hash == o2.hash and o1.eql?(o2) and  
for any two objects that you do not consider equal !o1.eql?(o2) (o1.hash may  
still be equal to o2.hash, but should not be).

> Ive heard of set, could that be used in this case to prevent duplicates  
> being added?

If uniq does not work, set does not work either. Once you implement hash and  
eql?, yes, set can be used.  
If you use Struct to define your class, like I demonstrated above hash and  
eql? will be defined automatically. If you can't use a struct, you could  
define them as such:  
class Thing  
&nbsp;&nbsp;attr\_accessor :name, :job  
&nbsp;&nbsp;def hash  
&nbsp;&nbsp;&nbsp;&nbsp;[name, job].hash  
&nbsp;&nbsp;end

&nbsp;&nbsp;def eql?(other)  
&nbsp;&nbsp;&nbsp;&nbsp;[name, job].eql?([other.name, other.job])  
&nbsp;&nbsp;end  
end

HTH,  
Sebastian

> **···**
>
> --  
> NP: Die Apokalyptischen Reiter - Heut' Ist Der Tag  
> Jabber: sepp2k@jabber.org  
> ICQ: 205544826

---

<div class="post-metadata">

**Author:** ![Adam\_Akhtar](https://avatars.discourse-cdn.com/v4/letter/a/c89c15/32.png) [@Adam\_Akhtar](https://rubytalk.org/u/Adam_Akhtar)\
**Post date:** [16 September 2008 09:59 UTC](https://rubytalk.org/t/getting-an-array-of-unique-objects-of-a-class-i-wrote/49076/5 "2008-09-16T09:59:35Z")

</div>

Thank you everyone for your reply. Ive implemented the hash and eql?  
definitions for my class and it worked. On a similiar note what do i  
have to do for my unit tests which compare two objects to work.

I.e.

assert\_equal(expected\_object, some\_method\_which\_returns\_an\_object())

where both the compared objects are instances of a class i defined.

So far my unit tests fail despite the variables within the objects being  
identical. the only difference is the object\_id which i guess is  
important.  
I impleted hash and eql? like above but the tests still dont pass.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Brian\_Candler](https://avatars.discourse-cdn.com/v4/letter/b/5f9b8f/32.png) [@Brian\_Candler](https://rubytalk.org/u/Brian_Candler)\
**Post date:** [16 September 2008 11:49 UTC](https://rubytalk.org/t/getting-an-array-of-unique-objects-of-a-class-i-wrote/49076/6 "2008-09-16T11:49:11Z")

</div>

Adam Akhtar wrote:

> Thank you everyone for your reply. Ive implemented the hash and eql?  
> definitions for my class and it worked. On a similiar note what do i  
> have to do for my unit tests which compare two objects to work.
> 
> I.e.
> 
> assert\_equal(expected\_object, some\_method\_which\_returns\_an\_object())

Look at the source for assert\_equal 🙂  
/usr/lib/ruby/1.8/test/unit/assertions.rb

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def assert\_equal(expected, actual, message=nil)  
...  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assert\_block(full\_message) { expected == actual }

So your object needs to implement '==' too.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).
