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]