Вычитание одного массива из другого в Ruby

У меня есть два массива задач - созданные и назначенные. Я хочу удалить все назначенные задачи из массива созданных задач. Здесь мой рабочий, но грязный, код:

    @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

Я уверен, что там лучший способ. Что это? Спасибо: -)

Ответ 1

Вы можете вычесть массивы в Ruby:

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

ary - other_ary → new_ary Разница в массиве

Возвращает новый массив, который является копией исходного массива, удаляя любые элементы, которые также отображаются в other_ary. Порядок сохраняется из исходный массив.

Он сравнивает элементы, используя их хэш и eql? методы эффективности.

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

Если вам нужно set-like behavior, см. класс библиотеки Set.

См. документацию Array.

Ответ 2

Вышеприведенное решение

a - b

удаляет все экземпляры элементов в массиве b из массива a.

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

В некоторых случаях вы хотите, чтобы результат был [1, 2, 3, 3, 5]. То есть вы не хотите удалять все дубликаты, но только отдельные элементы.

Вы можете достичь этого

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

Тест

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]

Код работает даже тогда, когда два массива не отсортированы. В этом примере массивы отсортированы, но это не требуется.