Rubyで1つの配列を別の配列から減算する


83

タスクの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

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


確かに、答えはあなたがそこでコーディングしたことを実行しているだけです。
baash05 2012年

回答:


177

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

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


2
Arg。私にとって大きな顔と手のひらの瞬間。どういうわけか、それはオブジェクトでは機能しないと思いました。うまくいきました-ありがとう!
ドクターオレンジ2009

28
これに注意して、最初にIRBでテストしてください。例:[5、5、5、5]-[5、5] = [] ...減算により、配列内の一意の要素が削除されます。
hagope 2011

9
また、これは機能しないことに注意してください[1,2]-[1,2,3] => []。しかし[1,2,3]-[1,2] => [3]。ああ。
Zabba 2012年

17
減算の観点から考えると、この最後の「落とし穴」は実際には理にかなっています。差分を求めていないものを減算するには... XからYを減算するように求めています... YにXにもないものがある場合、結果は「未定義」のようなものになるため、余分なY要素はX結果には含まれません。
ベイン

2
具体的にArray#-は、セットの違いです。これArray#|Array#+、連結ではなく、集合和集合の逆です(集合演算ではありません!)。
ymbirtt 2015年

9

上記の解決策

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つの配列がソートされていない場合でも機能します。この例では、配列は並べ替えられていますが、これは必須ではありません。


delete_elements_in適切なルビー(ルビー2.6.3p62)には使用できません
qaisjp

@qaisjp、それはライターによって定義されているからです。あなたもそれを定義しなければなりません。テストコードの上のコードを見てください。
ismailarilik
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.