18
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

配列の差分をとりたい

Last updated at Posted at 2016-02-11

Array#-があるけれど、

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

となり、左配列から、右配列に含まれる要素をすべて取り除いた配列が返る。
重複要素がありえるようなリストの差分を取る(つまり、集合演算ではない)ときにはちょっと使いにくい。
以下のように、引数要素の個数を考慮して差分をとりたい。

[ 1, 1, 1, 2, 2, 3, 3 ].remove [ 1 ]
# => [1, 1, 2, 2, 3, 3]

というわけで書いた。メソッド名にあまり良い名前が思い浮かばなかった。。。

class Array
  def remove r, reverse: false
    r = r.dup
    a = dup
    b = []

    a.reverse! if reverse
    a.each do |item|
      i = r.find_index item
      if i
        r.delete_at i
      else
        b << item
      end
    end
    b.reverse! if reverse
    b
  end
end

引数要素の個数を考慮して差分をとった配列を返す。

[ 1, 1, 1, 2, 2, 3, 3, 1 ].remove [ 1 ]
# => [1, 1, 2, 2, 3, 3, 1]

[ 1, 1, 1, 2, 2, 3, 3, 1 ].remove [ 1 ], reverse: true
# => [1, 1, 1, 2, 2, 3, 3]

2つのリストを合わせるときにも便利に使える(ような気がする)。

a = [1,2,3,3,4,4]
b = [2,4,4,7,9]

a + b           #=> [1, 2, 3, 3, 4, 4, 2, 4, 4, 7, 9]
a | b           #=> [1, 2, 3, 4, 7, 9]
a + b.remove(a) #=> [1, 2, 3, 3, 4, 4, 7, 9]

a & b                #=> [2, 4]
a.remove a.remove(b) #=> [2, 4, 4]
18
9
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?