同时筛选两个列表

16

我有三个列表:

del_ids = [2, 4]
ids = [3, 2, 4, 1]
other = ['a', 'b', 'c', 'd']

我的目标是删除del_ids,结果应为:

ids = [3, 1]
other = ['a', 'd']

我尝试着创建一个元素的掩码以保留它们 (mask = [id not in del_ids for id in ids]),并且计划将这个掩码应用到两个列表上。

但我感觉这不是一种很Pythonic的解决方案。请问您能告诉我如何更好地实现吗?

4个回答

20

压缩,筛选,再解压:

ids, other = zip(*((id, other) for id, other in zip(ids, other) if id not in del_ids))
zip() 方法将每个 id 与相应的 other 元素配对,生成器表达式过滤掉所有在 del_ids 中列出的 id,然后使用 zip(*..) 将剩余的配对拆分成单独的列表。
>>> del_ids = [2, 4]
>>> ids = [3, 2, 4, 1]
>>> other = ['a', 'b', 'c', 'd']
>>> zip(*((id, other) for id, other in zip(ids, other) if id not in del_ids))
[(3, 1), ('a', 'd')]

它将序列(来自生成器表达式的所有对)作为单独的参数应用于zip()函数。zip()看到zip(pair1, pair2, pair3, etc.),然后将所有这些对压缩成两个列表。 - Martijn Pieters
@BarnabasSzabolcs:(.. for .. in ..) 结构是一个生成器表达式。它很像列表推导式 ([.. for .. in ..]),但它不会首先在内存中构建一个新的列表。 - Martijn Pieters
啊,我明白了,谢谢!一旦我获得许可,我会接受这个答案。 - Barney Szabolcs
哇,真的吗?看起来我将能够在几年内记住并使用它... - Jblasco
@ersran9:当然,我也可以考虑更好的数据结构。但是也许顺序很重要(答案:使用OrderedDict),也许允许重复(那么使用元组序列)等等。 - Martijn Pieters
显示剩余4条评论

2
为了避免学习棘手的语法,请分两步完成。
other = [o for my_id, o in zip(ids, other) if my_id not in del_ids]
ids = [my_id for my_id in ids if my_id not in del_ids]

缺点
您必须按照正确的顺序执行语句,因此如果出现顺序更改的情况,则存在错误风险。

优点
它很直接,所以下次想要执行此操作时,您不必搜索Stackoverflow。


我喜欢你的方法,因为它非常简洁。 - Barney Szabolcs
1
另外,我希望id不是Python中的保留字...因为id将是一个常见的变量名。使用i会让我感到困惑,因为i通常指整数循环索引,而不是id。如果它是Python的实现细节,为什么他们不使用__id __()而不是id()呢? 那么,现在哪个更糟糕,拥有一个命名错误的变量还是拥有一个变量遮蔽内置变量?Martijn似乎认为前者更糟糕。 - Barney Szabolcs
谢谢Barney,我已经更改了变量名。 - Teitur

2

压缩、过滤、解压:

ids, other = zip(*filter(lambda (id,_): not id in del_ids, zip(ids, other)))

@Martijn:filter函数返回一个过滤后的仅包含2个元组的列表,所以我可以安全地解包它们。该死,你是对的,我已经做出了更正。 - Julien Grenier
1
是的,直到您的过滤器返回超过或少于2个元组为止。在您理解其含义之前,请勿复制我的解决方案并进行微小更改。:-P - Martijn Pieters
@MartijnPieters:在看你的回答之前,我实际上已经写了这个答案。我猜伟大的思想总是相似的 ;-P - Julien Grenier

1

将数据转换为 pandas 数据框并应用掩码:

del_ids = [2, 4]
ids = [3, 2, 4, 1]
other = ['a', 'b', 'c', 'd']
df = pd.DataFrame({'ids':ids,'other':other})
df = df[~df.ids.isin(del_ids)]
ids = df['ids'].tolist()
other = df['other'].tolist()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接