Uniq on custom objects

I cannot get uniq to work with an array of custom class-objects. It
seems
overriding hash is now enough. This is what I mean:

class Obj
attr_reader :name, :number
def initialize(name, number)
@name = name
@number = number
end
def hash
return @name.hash
end
end

a = [Obj.new(“apa”, 1), Obj.new(“apa”, 2), Obj.new(“smisk”, 3)]

=> [#<Obj:0x31baca8 @number=1, @name=“apa”>, #<Obj:0x31bac80 @number=2,
@name=“apa”>, #<Obj:0x31bac58 @number=3, @name=“smisk”>]

a.uniq

=> [#<Obj:0x31baca8 @number=1, @name=“apa”>, #<Obj:0x31bac80 @number=2,
@name=“apa”>, #<Obj:0x31bac58 @number=3, @name=“smisk”>]

But i want only one instance of “apa”, and it doesn’t matter which. Is
there
something else I have to override?

/D

Alle lunedì 29 ottobre 2007, daniel åkerud ha scritto:

return @name.hash

=> [#<Obj:0x31baca8 @number=1, @name=“apa”>, #<Obj:0x31bac80 @number=2,
@name=“apa”>, #<Obj:0x31bac58 @number=3, @name=“smisk”>]

But i want only one instance of “apa”, and it doesn’t matter which. Is
there something else I have to override?

/D

I think you also need to override eql? so that it returns true if the
two objects have the same name:

class Obj

def eql? other
@name.eql? other.name
end

end

a = [Obj.new(“apa”, 1), Obj.new(“apa”, 2), Obj.new(“smisk”, 3)]

p a.uniq

=> [#<Obj:0xb7b7f75c @name=“apa”, @number=1>, #<Obj:0xb7b7f57c
@name=“smisk”, @number=3>]

I hope this helps

Stefano

From: daniel åkerud [mailto:[email protected]]

a = [Obj.new(“apa”, 1), Obj.new(“apa”, 2), Obj.new(“smisk”, 3)]

=> [#<Obj:0x31baca8 @number=1, @name=“apa”>, #<Obj:0x31bac80

@number=2, @name=“apa”>, #<Obj:0x31bac58 @number=3, @name=“smisk”>]

a.uniq

=> [#<Obj:0x31baca8 @number=1, @name=“apa”>, #<Obj:0x31bac80

@number=2, @name=“apa”>, #<Obj:0x31bac58 @number=3, @name=“smisk”>]

But i want only one instance of “apa”, and it doesn’t matter

which. Is there something else I have to override?

hmm, that’s a unique requirement for uniq :slight_smile:
btw, there was a recent thread on removing dups, wc is similar in a way
to uniq.

anyway, try

~> a.group_by(& :name).map{|_,v|v[0]}

=> [#<Obj:0xba8c90 @name=“smisk”, @number=3>, #<Obj:0xba8d08
@name=“apa”, @number=1>]

sorry, i’m in ruby1.9 box right now. but the idea is that i group the
objects by name, and just get the first on each group.

kind regards -botp

2007/10/29, daniel åkerud [email protected]:

return @name.hash

=> [#<Obj:0x31baca8 @number=1, @name=“apa”>, #<Obj:0x31bac80 @number=2,
@name=“apa”>, #<Obj:0x31bac58 @number=3, @name=“smisk”>]

But i want only one instance of “apa”, and it doesn’t matter which. Is there
something else I have to override?

You can make your life much easier by using Struct:

Obj = Struct.new :name do
attr_accessor :number
def initialize(name, number)
self.name = name
self.number = number
end
end

irb(main):008:0> a = [Obj.new(“apa”, 1), Obj.new(“apa”, 2),
Obj.new(“smisk”, 3)]
=> [#, #, #]
irb(main):009:0> a.uniq
=> [#, #]

Kind regards

robert