使用 python 中其他列表的列表推导过滤嵌套列表

Filter nested list with list comprehension based on other list in python

提问人:hongdekong 提问时间:6/1/2022 最后编辑:hongdekong 更新时间:6/1/2022 访问量:536

问:

我有两个这样的列表:

a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]

我现在想过滤列表 a,只保留包含列表 b 中的项目。因此,所需的输出如下所示:

[[1,2,3],[2,3,4]]

我尝试了一些嵌套列表推导式,我能想到,但无法获得所需的输出。任何建议都是值得赞赏的。

python list-comprehension 嵌套列表

评论

2赞 Ethan Van den Bleeken 6/1/2022
你能展示你已经尝试过的东西吗?
0赞 hongdekong 6/1/2022
有些事情,但我只是在这里胡闹。我发现很难理解这一点:这些都没有产生预期的结果。[i for i in a if i in b in i][i for i in a if i in i in b][[i for i in a if i in b] for ele in a][[i for i in b] for i in a]

答:

1赞 baskettaz 6/1/2022 #1

你可以试试这样的东西:

print([i for i in a if any(map(i.__contains__,b))])

>>> [[1, 2, 3], [2, 3, 4]]

评论

3赞 Tomerikoo 6/1/2022
我个人也发现 with 的使用非常令人困惑。我会简单地写(它甚至少^_^了一个字符)map__contains__any(x in i for x in b)
0赞 baskettaz 6/1/2022
好点子,+1,我只是忘了更新它...... :)
1赞 Gabriel Markfjärd 6/1/2022 #2

列表推导和集合的组合将产生所需的结果。注意;如果是这种情况,我假设重复的项目和排序是不感兴趣的 - 一个集合将不起作用,因为它忽略排序并且只允许唯一的项目。

一个简单的列表理解就可以了,如下所示

filter_items = set(filter_items)
[sublist for sublist in original_list if not set(sublist).isdisjoint(filter_items)]

这个列表的理解主要有一个有趣的部分,即 .在这里,只有当子列表集与集合不相交时,您才保留子列表filter_items即子列表中没有filter_items。if not set(sublist).isdisjoint(filter_items)

对于给定的示例,提供的答案将产生以下结果:

>>> a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
>>> b = set([1,2])
>>> [sublist for sublist in a if not set(sublist).isdisjoint(b)]
[[1, 2, 3], [2, 3, 4]]

评论

0赞 Tomerikoo 6/1/2022
为什么不只是 ?如果交叉点不为空,则要保留列表...(set 方法不需要 set 作为参数)set(sublist).intersection(b)
0赞 STerliakov 6/1/2022
可以在理解之前做一个集合,以避免重复构建和使用(接受任何可迭代的,AFAIR)。bb.isdisjoint(sublist)isdisjoint
1赞 STerliakov 6/1/2022
@tomerikoo因为这是不必要的工作,所以你真的不需要交叉点——你只想知道这个交叉点是否不是空的。 这里更优化。isdisjoint
0赞 Tomerikoo 6/1/2022
@SUTerliakov 来自文档:“如果集合没有其他元素,则返回 True。当且仅当集合的交集是空集合时,集合才是不相交的。我怀疑运行时存在(关键)差异......
0赞 STerliakov 6/1/2022
@tomerikoo 有趣的是,当我有时间时,我会测量。但是,我想它执行类似于的短路评估,并且会在第一个匹配项目后返回,同时无论如何都会检查整个集合。就像那样不会耗尽迭代器,并且会在第一次之后停止。我真的怀疑这是像这样实现的,它是低效的。isdisjointanyFalseintersectionany(iterator)Trueisdisjointnot bool(intersection)
1赞 Ethan Van den Bleeken 6/1/2022 #3

我会尝试这样的事情:

a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]

result = [lst for lst in a if any(x in lst for x in b)]
0赞 cards 6/1/2022 #4

使用一种方法可以模拟交叉点:setin

a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]

b_as_set = set(b)

out = [l for l in a if b_as_set.intersection(l)]
# [[1, 2, 3], [2, 3, 4]]
0赞 damien toh 6/1/2022 #5

我会尝试这样的事情。

a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]

print([lst for lst in a if any([item in b for item in lst])])

评论

0赞 Tomerikoo 6/1/2022
无需在通话中创建列表any