On 2/26/08, Christopher Swasey <christopher.swasey / gmail.com> wrote:
> On 2/26/08, Zouplaz <user / domain.invalid> wrote:
>  > Hello, sorry if this question is stupid but I can't find a solution
>  >  after several readings about Arrays
>  >
>  >  Array 'a' contains several objets (ruby classes instances), each
>  >  instance have an id property
>  >
>  >
>  >  I need a clean solution to return true if array 'a' contains an instance
>  >  with id foo without iterating the whole array.
>  >
>  >  Example
>  >
>  >  def add_user(user)
>  >    unless users.include?(user.id)
>  >      users << user
>  >    end
>  >  end
>  >
>  >  users.include? statement is wrong because we compare id's with objects.
>  >  Which is the right way to do it ?
>
>
> Read up on the Enumerable module.
>  http://www.ruby-doc.org/core/classes/Enumerable.html#M003153.
>
>  You have a couple of options. The simplest code-wise is to use find:
>
>  def add_user(user)
>   unless users.find { |u| u.id == user.id }
>     users << user
>   end
>  end
>
>  Potentially marginally more efficient is #map and then calling
>  #include? on the result
>
>  def add_user(user)
>   unless users.map { |u| u.id }.include?(user.id)
>     users << user
>   end
>  end
>
>
>  Christopher
>

Additionally, if a unique user always has the same id (for instance,
they're defined in a database and the id is the primary key), then you
can override #== in your class to compare ids to determine equality.
Then you can just call #include? with the user directly:

def add_user(user)
  unless users.include?(user)
    users << user
  end
end

This is almost definitely the most efficient solution, but it does
require you to modify your class.

Best,
Christopher