Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subtracting one Array from another in Ruby

I've got two arrays of Tasks - created and assigned. I want to remove all assigned tasks from the array of created tasks. Here's my working, but messy, code:

    @assigned_tasks = @user.assigned_tasks
    @created_tasks = @user.created_tasks

    #Do not show created tasks assigned to self
    @created_not_doing_tasks = Array.new
    @created_tasks.each do |task|
        unless @assigned_tasks.include?(task)
            @created_not_doing_tasks << task
        end
    end

I'm sure there's a better way. What is it? Thanks :-)

like image 882
doctororange Avatar asked Jul 28 '09 06:07

doctororange


People also ask

How do you subtract two arrays?

Description. C = A - B subtracts array B from array A by subtracting corresponding elements. The sizes of A and B must be the same or be compatible. If the sizes of A and B are compatible, then the two arrays implicitly expand to match each other.

How do you subtract an element from an array?

Given an integer k and an array arr[], the task is to repeat the following operation exactly k times: Find the minimum non-zero element in the array, print it and then subtract this number from all the non-zero elements of the array. If all the elements of the array are < 0, just print 0.


2 Answers

You can subtract arrays in Ruby:

[1,2,3,4,5] - [1,3,4]  #=> [2,5]

ary - other_ary → new_ary Array Difference

Returns a new array that is a copy of the original array, removing any items that also appear in other_ary. The order is preserved from the original array.

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

[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]

If you need set-like behavior, see the library class Set.

See the Array documentation.

like image 138
hobodave Avatar answered Oct 04 '22 06:10

hobodave


The above solution

a - b

deletes all instances of elements in array b from array a.

[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ]  #=>  [ 3, 3, 5 ]

In some cases, you want the result to be [1, 2, 3, 3, 5]. That is, you don't want to delete all duplicates, but only the elements individually.

You could achieve this by

class Array
  def delete_elements_in(ary)
    ary.each do |x|
      if index = index(x)
        delete_at(index)
      end
    end
  end
end

test

irb(main):198:0> a = [ 1, 1, 2, 2, 3, 3, 4, 5 ]
=> [1, 1, 2, 2, 3, 3, 4, 5]
irb(main):199:0> b = [ 1, 2, 4 ]
=> [1, 2, 4]
irb(main):200:0> a.delete_elements_in(b)
=> [1, 2, 4]
irb(main):201:0> a
=> [1, 2, 3, 3, 5]

The code works even when the two arrays are not sorted. In the example, the arrays are sorted, but this is not required.

like image 23
Zack Xu Avatar answered Oct 04 '22 05:10

Zack Xu