Stop duplicates from adding Ruby objects to array

how can I remove duplicate elements from an array of ruby ​​objects using an object attribute to match against identical objects.

with an array of basic types, I can use a set.

eg.

array_list = [1, 3, 4 5, 6, 6]
array_list.to_set 
=> [1, 2, 3, 4, 5, 6]

      

Can this method be adapted to work with object attributes?

thanks

+2


a source to share


5 answers


If you can write it to your objects to use eql?

, you can use uniq

.



+2


a source


I think you are putting the cart in front of the horse. Are you asking yourself, "How can I get uniq

to delete objects that are not equal?" But you have to ask yourself, "Why are these two objects not equal, even though I think they are?"

In other words: you seem to be trying to get around the fact that your objects violated equality semantics, when what you really should be doing is just fixing those broken equality semantics.

Here is an example for Product

where two products are considered equal if they have the same type number:



class Product
  def initialize(type_number)
    self.type_number = type_number
  end

  def ==(other)
    type_number == other.type_number
  end

  def eql?(other)
    other.is_a?(self.class) && type_number.eql?(other.type_number)
  end

  def hash
    type_number.hash
  end

  protected

  attr_reader :type_number

  private

  attr_writer :type_number
end

require 'test/unit'
class TestHashEquality < Test::Unit::TestCase
  def test_that_products_with_equal_type_numbers_are_considered_equal
    assert_equal 2, [Product.new(1), Product.new(2), Product.new(1)].uniq.size
  end
end

      

+3


a source


how about uniq

   a = [ "a", "a", "b", "b", "c" ]
   a.uniq   #=> ["a", "b", "c"]

      

you can use it on site too!

0


a source


Should I use Array

or be used Set

instead? If order is not important, then the latter will make it more efficient to check for duplicates.

0


a source


thanks for your answers .. uniq works as soon as i added the following to my object model

def ==(other)
    other.class == self.class &&
    other.id  == self.id
end
alias :eql? :==

      

-1


a source







All Articles