如何根据列表中另一个字典的值从列表中删除字典?

时间:2013-11-25 23:50:24

标签: python list dictionary

我花了大约6个小时,所以我觉得有理由提问。 :)

我的问题

list1 = [
       {extension: 1000, id: 1}
       {extension: 1001, id: 1}
       {extension: 1000, id: 2}
        ]

list2 = [
       {Stationextension: 1000, id: 1, name: bob}
       {Stationextension: 1001, id: 1, name: sal}
       {Stationextension: 1000, id: 2, name: cindy}
        ]

我的伪代码就是这个。

Delete list2[d] (whole dictionary from list of dicts) where list1[d]['extension'] == list2[d]['Stationextension'] AND id == id.

如果重要的话,列表1要小得多,并且必须保持相对于列表2保持不变。

使用Python3.3,我有类似

的东西
[x for x in list2 if (list1[x]['stationExtension'] == x.get('extension'))]

谢谢!

4 个答案:

答案 0 :(得分:1)

list2 = [x for x in list2 if {'extension': x['Stationextension'], 'id': x['id']} not in list1]

或者,如果您知道长度和索引将匹配:

list2 = [y for x,y in itertools.izip(list1, list2) if x['extension'] == y['StationExtension'] and x['id'] == y['id']]

答案 1 :(得分:1)

正确的方法是为作业使用正确的数据结构。而不是弄清楚如何基于密钥搜索列表,而是使用带有该密钥的字典。例如:

dict1 = {x['extension']: x for x in list1}

现在,你可以写下这个:

[x for x in list2 if x['stationExtension'] in dict1}

在您的问题的其他地方,您似乎想要使用扩展名将ID(而不仅仅是扩展名)作为密钥。但这也很容易;你可以使用元组:

dict1 = {(x['extension'], x['id']): x for x in list1}

[x for x in list2 if (x['stationExtension'], x['id']) in dict1}

如果你想知道为什么你的代码不起作用......让我们来看看它:

[x for x in list2 if (list1[x]['stationExtension'] == x.get('extension'))]

list1[x]正在尝试将dict用作索引,这并不意味着什么。你真正想说的是“如果,对于list1的任何元素,element['stationExtension'] == x.get('extension')”。你几乎可以直接将它翻译成Python:

[x for x in list2 
 if any(element['stationExtension'] == x.get('extension')
        for element in list1)]

当然要将and element['id'] == x['id']添加到条件的末尾。

但同样,dict是一个更好的解决方案。除了阅读和写入更简单之外,它也更有效率。搜索列表中的任何匹配项都需要检查列表中的每个元素;在dict中搜索任何匹配项只需要散列密钥并在哈希表中查找。所以,这种方式需要O(NM)时间(其中N是list1的长度,M是list2的长度),而dict只需要O(M)时间。

答案 2 :(得分:0)

Python 2.7:

removelist=[]
for i,x in enumerate(list2):
    if x['Stationextension'] == list1[i]['extension'] and x['id'] == list1[i]['id']:
        removelist+=[i]

一旦你决定要删除什么:

for x in removelist:
    del list1[x]

答案 3 :(得分:0)

假设您要在" Stationextention"中删除list2中具有相同值的项目。在list2和" extention"在名单1 - 您最好首先创建一个包含要删除的所有值的集合 - 这样可以避免每次要检查条目是否保留时进行线性搜索:

indexes = set(item["extention"] for item in list1)

而且 - 发生的一件事是,您通常无法在列表上进行迭代并从中删除项目:

new_list2 = []
for item in list2:
    if item["Stationextention"] not in indexes: 
         new_list2.append(item)

list2 = new_list2