Ruby Reminder: Array Subtraction

Just a reminder when working with arrays of objects generated with Active Record.

[Model.find(1), Model.find(2), Model.find(3)] -
  [Model.find(1)] != [Model.find(2), Model.find(3)]

This does not behave as you would expect, because array subtraction compares elements on their object ids. Each find generates a new object, with a new id, so subtraction does not work. To get the behavior desired, do this instead:

to_be_removed = [Model.find(1)].map{|m| m.id}
[Model.find(1), Model.find(2), Model.find(3)].
  delete_if{|m| to_be_removed.include?(m.id)}

It’s not as beautiful, but it gets the job done.

1 Comment »

  1. kajinski said,

    February 22, 2008 @ 12:05 pm

    apparently this is also true with arrays containing hashes. if you create two arrays with an identical hash element in each, subtraction fails:

    >> arr1 = [{:foo=>'bar'}]
    => [{:foo=>"bar"}]
    >> arr2 = [{:foo=>'bar'}]
    => [{:foo=>"bar"}]
    >> arr1 == arr2
    => true
    >> arr1[0] == arr2[0]
    => true
    >> newarr = arr1 – arr2
    => [{:foo=>"bar"}]

RSS feed for comments on this post · TrackBack URI

Leave a Comment