如果项目包含黑名单中的条目,则从列表中删除项目

时间:2014-08-06 00:08:34

标签: python list dictionary

我有一个词典列表:

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。

4 个答案:

答案 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