这是一个定义不明确的问题。我可以想到列表“减法”的几个非等价定义,其中两个已经被表示:截断(通过切片) - 串联的真正逆;和过滤,类似于集合的“减法”(真正的相对互补)的定义。对于过滤,使用列表推导而不是a
转换b
为集合是最好的方法。(即larsvegas的回答。)
但尚未考虑的一个版本是减法的多集定义。Python 的Counter
类型为我们提供了一个多重集:
>>> from collections import Counter
>>> a = [3, 4, 5]
>>> b = [4, 5]
>>> a_counter = Counter(a)
>>> b_counter = Counter(b)
>>> a_counter
Counter({3: 1, 4: 1, 5: 1})
>>> b_counter
Counter({4: 1, 5: 1})
>>> a_counter - b_counter
Counter({3: 1})
当然,这不会保留顺序,但我们可以通过a
基于以下结果进行过滤来解决这个问题a_counter - b_counter
:
def subtract_lists(a, b):
multiset_difference = Counter(a) - Counter(b)
result = []
for i in a:
if i in multiset_difference:
result.append(i)
multiset_difference -= Counter((i,))
return result
这有几个不错的属性。它保持秩序;它的作用是串联的真正逆;它在可以包含重复项的数据类型上实现了直观一致的减法版本;它在线性时间内工作。
>>> subtract_lists(a, b)
[3]
>>> subtract_lists([1, 2, 3, 4], [2, 3, 4])
[1]
>>> subtract_lists([1, 2, 3, 4], [2, 4])
[1, 3]
>>> subtract_lists([1, 2, 3, 4, 4, 4], [2, 4])
[1, 3, 4, 4]