根据另一个列表有选择地从列表列表中删除所有事件

Selectively remove all occurrences from a list of lists based off of another list

我找了好几个小时都没能找到完全我需要的东西,所以我想我'问。我正在尝试从基于另一个字典列表的列表列表中删除元素。我有一个我不想出现在列表列表中的项目列表。

exclude_list = [{'arb_field_1': '0', 'arb_field_2': '59',
                 'surrogate_key': '0502f5fb0731b5afc'},
                {'arb_field_1': '0', 'arb_field_2': '62',
                 'surrogate_key': '1676c663914864973'},
                {'arb_field_1': '0', 'arb_field_2': '62',
                 'surrogate_key': '2fc1ed4adffbb635'}]

然后我有我的主列表,我想根据字典排除列表中的 surrogate_key 从中删除元素。

prim_list = [['0502f5fb0731b5afc', 'bla_bla_bla', 'foo_bar1'],
             ['0502f5fb0731b5afc', 'john_smith', 'dummy_data_elem1'],
             ['002b2a71e8b514', '5450464', 'data_i_dont_care_about'],
             ['2fc1ed4adffbb635', '05d3mh', 'obfuscated_field1'],
             ['12319618913119', 'granny_apples', 'filler_filler']]

我有以下有效的循环(感觉不是很 pythonic,但我是 Python 的新手,所以我愿意接受有关建议)..但是 only 删除匹配的一个实例,其中我需要删除 all 个实例比赛。

for exclude_list_item in exclude_list:
    for i, v in enumerate(prim_list):
        if v[0] == exclude_list_item.get('surrogate_key'):
            prim_list.remove(prim_list[i])

我最终想要的是这样的列表列表:

prim_list = [['002b2a71e8b514', '5450464', 'data_i_dont_care_about'],
             ['12319618913119', 'granny_apples', 'filler_filler']]

使用 list.remove 从您的列表中删除 第一个实例 ,而不是每个实例。为了让事情变得简单,让我们做一个单一的过程,我们将 surrogate_keys 累积到一个集合中以进行有效的成员测试:

>>> exclude_list = [{'arb_field_1': '0', 'arb_field_2': '59', 'surrogate_key': '0502f5fb0731b5afc'}, {'arb_field_1': '0', 'arb_field_2': '62', 'surrogate_key': '1676c663914864973'}, {'arb_field_1': '0', 'arb_field_2': '62', 'surrogate_key': '2fc1ed4adffbb635'}]
>>> prim_list = [['0502f5fb0731b5afc', 'bla_bla_bla', 'foo_bar1'], ['0502f5fb0731b5afc', 'john_smith', 'dummy_data_elem1'], ['002b2a71e8b514', '5450464', 'data_i_dont_care_about'], ['2fc1ed4adffbb635', '05d3mh', 'obfuscated_field1'], ['12319618913119', 'granny_apples', 'filler_filler']]
>>> exclude_key = set()
>>> for d in exclude_list:
...     key = d.get('surrogate_key')
...     if key is not None:
...         exclude_key.add(key)
...

然后,简单地使用列表理解进行过滤:

>>> prim_list = [sub for sub in prim_list if sub[0] not in exclude_key]
>>> prim_list
[['002b2a71e8b514', '5450464', 'data_i_dont_care_about'], ['12319618913119', 'granny_apples', 'filler_filler']]

所以,您想要移除以移除所有出现的 exclude_list_item,而不仅仅是第一个?

我建议改为构建一个新列表。因此,您遍历该列表,如果该项目不在您的排除列表中,则将该项目附加到新的列表项目。

原因是从列表中删除比删除多个随机项目的计算成本更高。

new_prim_list = []
for v in prim_list:
    for exclude_list_item in exclude_list:
        if v[0] == exclude_list_item.get('surrogate_key'):
             break
    else:
        new_prim_list.append(v)
prim_list = new_prim_list

编辑:修复代码

请注意,这不会影响对该列表的其他引用,因此如果您想将列表修改为函数的一部分,那么调用者将不会在他的列表中看到修改。任何直接将新数组分配给 prim_list 的解决方案都会出现同样的问题, 像任何形式的构造

prim_list = [...]

首先过滤一些集合中的代理键。

set_surr = set( [i.get('surrogate_key') for i in exclude_list] )

现在我们可以创建新列表并使用上面的集合作为查找。

prim_list = [ i for i in prim_list if i[0] not in set_surr ]

一个衬垫解决方案:

prim_list = [ i for i in prim_list if i[0] not in set( [j.get('surrogate_key') for j in exclude_list] ) ]