Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rail bitwise operators (&) for the complex types arrays

I am trying to use the bitwise operator (&) for the arrays in the Ruby on Rails

When I have the simple type arrays

one = ["one", "two", "three"]
two = ["one", "two", "three"]

And have this code

puts (one & two)

I get the output:

one two three

However, when I am having the complex types arrays

list1 = [Someitem.new("1", "item1"),Someitem.new("2", "item2"),Someitem.new("3", "item3"),Someitem.new("4", "item4")]
list2 = [Someitem.new("1", "item1"),Someitem.new("2", "item2"),Someitem.new("3", "item3"),Someitem.new("4", "item4")]

For the class where I do override the to_s method

class Someitem
    attr_accessor :item_id, :item_name
    def initialize(item_id, item_name)
      self.item_id = item_id;
      self.item_name= item_name;
    end
    
   def to_s
     item_name
   end  
end

And have this code

puts (list1 & list2)

I get nothing in the output

What can I do to get the output for the complex types arrays using the bitwise & operator to find common values within those two lists?

like image 331
James Avatar asked Feb 19 '26 16:02

James


1 Answers

The Ruby 3.0 docs for Array#& say:

[...] items are compared using eql?

The Ruby 2.7 docs for Array#& say:

It compares elements using their hash and eql? methods for efficiency

So in order to get this working for your class, you have to implement / override eql? and (for 2.7 compatibility) hash according to the docs. There are many ways to do this, here's a simple approach:

class Someitem

  # ...

  def hash
    [item_id, item_name].hash
  end

  def eql?(other)
    return false unless other.is_a?(Someitem)

    [item_id, item_name] == [other.item_id, other.item_name]
  end
  alias == eql?  # <- this isn't needed but convenient
end

The above implementation uses item_id and item_name to calculate the object's hash and to determine object equality:

Someitem.new("1", "item1").hash == Someitem.new("1", "item1").hash
#=> true

Someitem.new("1", "item1").eql? Someitem.new("1", "item1")
#=> true

[Someitem.new("1", "item1")] & [Someitem.new("1", "item1")]
#=> [#<Someitem:0x00007f8ff505d228 @item_id="1", @item_name="item1">]
like image 80
Stefan Avatar answered Feb 21 '26 06:02

Stefan