How to remove duplicates from an array with custom objects

When I call first_array | second_arrayon two arrays containing user objects:

first_array = [co1, co2, co3]
second_array =[co2, co3, co4]

he returns [co1, co2, co3, co2, co3, co4]. It does not remove duplicates. I tried to call uniqthe result, but it did not work either. What should I do?

Update:

This is a custom object:

class Task
    attr_accessor :status, :description, :priority, :tags
    def initiate_task task_line
        @status = task_line.split("|")[0]
        @description = task_line.split("|")[1]
        @priority = task_line.split("|")[2]
        @tags = task_line.split("|")[3].split(",")
        return self
    end

    def <=>(another_task)
        stat_comp = (@status == another_task.status)
        desc_comp = (@description == another_task.description)
        prio_comp = (@priority == another_task.priority)
        tags_comp = (@tags == another_task.tags)
        if(stat_comp&desc_comp&prio_comp&tags_comp) then return 0 end
    end
end

and when I create several instances of type Task and drop them into two different arrays, and when I try to call '|' nothing happens on them, it simply returns an array that includes both the first and second elements of the array without deleting duplicates.

+4
source share
6 answers

, , . eql? , , Array , Ruby Array:

def eql?(other_obj)
  # Your comparing code goes here
end

def hash
  #Generates an unique integer based on instance variables
end

:

class A

  attr_accessor :name

  def initialize(name)
    @name = name
  end

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

  def hash
    @name.hash
  end
end

a = A.new('Peter')
b = A.new('Peter')

arr = [a,b]
puts arr.uniq

b ,

, !

+3

uniq , , . :

class Task
  attr_accessor :n
  def initialize(n)
    @n = n
  end
end

t1 = Task.new(1)
t2 = Task.new(2)
t3 = Task.new(2)

a = [t1, t2, t3]

a.uniq
#=> [t1, t2, t3] # because all 3 objects are unique

a.uniq { |t| t.n }
#=> [t1, t2]     # as it comparing on the value of n in the object
+2

Array # |, , eql?, Object ==. , mixin Comparable -, <=>, - .

<=> :

def <=>(obj)
    return -1 if this < obj
    return 0 if this == obj
    return 1 if this > obj
end
0

"", , :

a = Task.new # => #<Task:0x007f8d988f1b78> 
b = Task.new # => #<Task:0x007f8d992ea300> 
c = [a,b]    # => [#<Task:0x007f8d988f1b78>, #<Task:0x007f8d992ea300>] 
a = Task.new # => #<Task:0x007f8d992d3e48> 
d = [a]      # => [#<Task:0x007f8d992d3e48>]  
e = c|d      # => [#<Task:0x007f8d988f1b78>, #<Task:0x007f8d992ea300>, \
                   #<Task:0x007f8d992d3e48>] 

, e = [a, b, a]? , , a #<Task:0x007f8d988f1b78>. , , e => [#<Task:0x007f8d988f1b78>, b, a]

0

, , uniq (hash eql?).

class Task

    METHODS = [:status, :description, :priority, :tags]
    attr_accessor *METHODS

    def initialize task_line
        @status, @description, @priority, @tags = *task_line.split("|")
        @tags = @tags.split(",")
    end

    def eql? another_task
       METHODS.all?{|m| self.send(m)==another_task.send(m)}
    end

    alias_method :==, :eql? #Strictly not needed for array.uniq

    def hash
      [@status, @description, @priority, @tags].hash
    end

end


x = [Task.new('1|2|3|4'), Task.new('1|2|3|4')]
p x.size #=> 2
p x.uniq.size #=> 1
0

fsaravia , . Ruby 2.3.1 Ruby 2.4.0.

, , , fsaravia , . , :

class A
  attr_accessor :name

  def initialize(name)
    @name = name
  end

  def eql?(other)
    hash.eql?(other.hash)
  end

  def hash
    name.hash
  end
end

a = A.new('Peter')
b = A.new('Peter')

arr = [a,b]
puts arr.uniq

Please do not mind what I deleted @in my example. This will not affect the decision as such. Exactly this, IMO, there was no reason to access the instance variable directly, because for this reason the read method was set.

So ... what I really changed is found inside the method eql?where I used hashinstead name. What is it!

0
source

All Articles