Note, the reason I can't just use my_array.uniq is that the array is
made up of objects which are themselves unique, it is just that some
elements share the same property (and these are the ones I want to
collapse down to just one object).
Robert Dober wrote:
Many thanks for this, and you ahve exactly described what I am wanting
to do. Unfortunately it is throwing up 'undefined method `tap' for
nil:NilClass (NoMethodError)'. I tried figuring this out for myself but
no joy Any ideas?
···
On Fri, May 14, 2010 at 12:47 PM, Toby Rodwell <trodwell@iee.org> wrote:
ah a #unique_by, I therefore conclude that you want to keep one
element with the given property.
module Enumerable
def unique_by &blk
keys = {}
reject{ | ele |
key = blk[ele]
keys[key].tap{ keys[key]=true }
}
end
end
p [*1..10].unique_by{ |x| x % 3 }
Could'nt come up with something more concise
HTH
R.
The code is ruby 1.9 only I think. Another way for 1.8.6:
module Enumerable
def unique_by &blk
keys = {}
find_all{ | ele |
key = blk[ele]
keys.has_key?(key) ? false : keys[key] = true
}
end
end
p [1,2,3,4,5].unique_by{ |x| x % 3 }
Or you can temporarily redefine eql? and hash:
class Foo
attr_reader :a
def initialize(a) @a = a
end
end
bar = Foo.new(1)
baz = Foo.new(2)
boz = Foo.new(2)
puts [bar,baz,boz].uniq.size
class Foo
alias_method :old_eql?, :eql?
alias_method :old_hash, :hash
def eql?(baz) @a == baz.a
end
def hash @a.hash
end
end
puts [bar,baz,boz].uniq.size
class Foo
alias_method :eql?, :old_eql?
alias_method :hash, :old_hash
end
puts [bar,baz,boz].uniq.size
Alex Gutteridge
···
On Fri, 14 May 2010 22:03:21 +0900, Toby Rodwell <trodwell@iee.org> wrote:
Robert Dober wrote:
Many thanks for this, and you ahve exactly described what I am wanting
to do. Unfortunately it is throwing up 'undefined method `tap' for
nil:NilClass (NoMethodError)'. I tried figuring this out for myself but
no joy Any ideas?
On Fri, May 14, 2010 at 12:47 PM, Toby Rodwell <trodwell@iee.org> wrote:
ah a #unique_by, I therefore conclude that you want to keep one
element with the given property.
module Enumerable
def unique_by &blk
keys = {}
reject{ | ele |
key = blk[ele]
keys[key].tap{ keys[key]=true }
}
end
end
p [*1..10].unique_by{ |x| x % 3 }
Could'nt come up with something more concise
HTH
R.