此问题已经在这里有了答案:
我目前正在使用数据结构列表,并且想知道如何删除在一个列表中发现的在另一个列表中出现的所有元素。我在Stack Overflow上看到了几个示例,这些示例涉及从列表中删除单个元素,但是对于删除多个类型相同元素的实例(例如下面的示例,而没有手动删除每个实例)。例如,给定以下两个列表:
friends_pets = ['Chicken', 'Chicken' 'Dog', 'Pigeon', 'Dog', 'Cat', 'Cat', 'Cat']
personal_pets = ['Dog', 'Cat']
我希望我的函数返回:
>>> ['Chicken', 'Chicken', 'Pigeon']
[我认为使用filter()方法通过remove()返回所需的列表似乎是最理想的,但是,我很难访问Python存储在特定地址的信息。
for pet in personal_pets:
filter(pet, friends_pets)
>>> <filter object at 0x10bfa2d90>
>>> <filter object at 0x10bfa2e50>
我什至尝试跑步:
for pet in personal_pets:
list(filter(pet, friends_pets))
但是,它声明'str'对象是不可调用的。
我使用remove()得到的最接近的是:
for pet in personal_pets:
friends_pets.remove(pet)
>>> ['Chicken', 'Chicken', 'Pigeon', 'Dog', 'Cat', 'Cat', 'Cat']
要使用filter
,使用的功能是lambda,它可以过滤掉不需要的宠物。在此,使用的列表new
不会破坏friends_pets
列表。否则,您可以使用该数组代替new
。
但是这种方法很浪费,因为它为personal_pets中的每只宠物重建了新的数组
>>> new = []
>>> new = [] + friends_pets
>>> for pet in personal_pets:
new = list(filter(lambda x: x != pet, new))
>>> new
['Chicken', 'Chicken', 'Pigeon']
使用列表推导可以更简单地完成。
>>> L = [pet for pet in friends_pets if pet not in set(personal_pets)]
>>> L
['Chicken', 'Chicken', 'Pigeon']
如果列表很大,则在此处使用集合将允许加速
更新:必须在friends_pets
中添加缺少的逗号
friends_pets = ['Chicken', 'Chicken', 'Dog', 'Pigeon', 'Dog', 'Cat', 'Cat', 'Cat']
在第二次出现鸡和狗之间不见了。奇怪的是,它把它们当作一个字符串,我不明白为什么。
使用set
将运行时间保持在O(n)范围内。
您可以做很多事情。
如果输入可能很大,请使用生成器:
def exclude_items(original_list, items_to_exclude):
# Create a set as lookup time is O(1).
# It can be O(log N) in case of collisions though still better than O(n) without it
to_exclude = set(items_to_exclude)
for item in original_list:
if item not in to_exclude:
yield item
没有生成器:
def exclude_items(original_list, items_to_exclude):
to_exclude = set(items_to_exclude)
return [item for item in original_list if item not in to_exclude]