我有一个词典列表:
lst = [
{'name': 'dave', 'age': 23, 'friends': ['richard', 'mike']},
{'name': 'bob', 'age': 26, 'friends': ['tom', 'mike', 'steve']},
{'name': 'bill', 'age': 30, 'friends': ['tom', 'jeff']},
{'name': 'nathan', 'age': 32, 'friends': ['steve', 'mike']}
]
我有一个“黑名单”
blacklist = ['steve', 'richard']
我想摆脱所有在friends
列表中列入黑名单的词典 - 在这种情况下,我只剩下bill
:
lst = [
{'name': 'bill', 'age': 30, 'friends': ['tom', 'jeff']}
]
每当我尝试接近这个时,我最终会得到这个疯狂的循环集 - 将索引添加到列表中然后再次迭代它并删除该索引处的项目。我假设有更好的方法。我不确定我是应该使用一种嵌套列表理解还是使用lambda。
答案 0 :(得分:5)
只需使用列表理解和过滤条件
[itm for itm in lst if all(friend not in blacklist for friend in itm["friends"])]
如果blacklist
是一个较大的列表,您可能希望将其转换为set
,就像这样
blacklist = {'steve', 'richard'}
集合将提供比列表更快的查找,因为查找在集合中以恒定时间发生,而在列表中的间隔时间内发生。
使用all
的优点是,如果其中一个迭代给出错误,它会短路并立即返回。因此,在大多数情况下,不需要消耗整个迭代。
答案 1 :(得分:3)
这是一个单行:
out = [d for d in lst if not any(x in blacklist for x in d['friends'])]
输出:
[{'age': 30, 'friends': ['tom', 'jeff'], 'name': 'bill'}]
我们制作了一个新列表,过滤掉d['friends']
中任何项目也位于我们blacklist
中的项目。
其他答案'但是,关于集合的注释是正确的。如果你正在处理大型列表,你肯定会使用它们,尽管你可能不会注意到较小的列表大小。
答案 2 :(得分:3)
如果您将两个列表都转换为集合,则可以有效地测试是否有任何朋友在黑名单中。然后它是一个简单的集合交集,看看是否有任何重叠。
试试这个:
blacklist = set(blacklist)
lst = [item for item in lst if not set(item["friends"]) & blacklist]
答案 3 :(得分:1)
上述答案都很好,但问题也可以在原地解决,而无需使用旧列表创建新列表。不知道这是不是你想要的,但值得把它发布在这里,
i=0
while( len(lst) > i ):
if any( x in blacklist for x in lst[i]['friends'] ):
del(lst[i])
else:
i += 1