私はこのようなことをします:
from collections import defaultdict
a = [1, 2, 3]
b = [1, 2, 3, 1, 2, 3]
# Build up the count of occurrences in b
d = defaultdict(int)
for bb in b:
d[bb] += 1
# Remove one for each occurrence in a
for aa in a:
d[aa] -= 1
# Create a list for all elements that still have a count of one or more
result = []
for k, v in d.iteritems():
if v > 0:
result += [k] * v
または、もう少しあいまいにしたい場合は、次のようにします。
from operator import iadd
result = reduce(iadd, [[k] * v for k, v in d.iteritems() if v > 0], [])
defaultdict は、各キーの出現回数を生成します。から構築されるb
と、 でキーが出現するたびに減分されa
ます。次に、まだ残っている要素を出力して、それらが複数回発生するようにします。
defaultdict は python 2.6 以降で動作します。それ以降の python (2.7 以降だと思います) を使用している場合は、collections.Counter
.
後で: これを一般化して、カウンター スタイルの defaultdict の減算を作成することもできます。
from collections import defaultdict
from operator import iadd
a = [1, 2, 3, 4, 5, 6]
b = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
def build_dd(lst):
d = defaultdict(int)
for item in lst:
d[item] += 1
return d
def subtract_dd(left, right):
return {k: left[k] - v for k, v in right.iteritems()}
db = build_dd(b)
da = build_dd(a)
result = reduce(iadd,
[[k] * v for k, v in subtract_dd(db, da).iteritems() if v > 0],
[])
print result
しかし、そのreduce
表現は今ではかなりあいまいです。
さらに後で: python 2.7 以降では、 を使用するcollections.Counter
と、次のようになります。
from collections import Counter
base = [1, 2, 3]
missing = [4, 5, 6]
extra = [7, 8, 9]
a = base + missing
b = base * 4 + extra
result = Counter(b) - Counter(a)
print result
assert result == dict([(k, 3) for k in base] + [(k, 1) for k in extra])