web-dev-qa-db-ja.com

Rubyである配列から別の配列を引く

タスクの配列が2つあります-作成して割り当てました。作成されたタスクの配列から割り当てられたすべてのタスクを削除したい。これが私の作業ですが、面倒なコードです:

    @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

もっと良い方法があると確信しています。それは何ですか?ありがとう:-)

76
doctororange

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を参照してください。

Array のドキュメントを参照してください。

158
hobodave

上記の解決策

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
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]

コードは、2つの配列がソートされていない場合でも機能します。この例では、配列はソートされていますが、これは必須ではありません。

5
Zack Xu