提问人:hongdekong 提问时间:6/1/2022 最后编辑:hongdekong 更新时间:6/1/2022 访问量:536
使用 python 中其他列表的列表推导过滤嵌套列表
Filter nested list with list comprehension based on other list in python
问:
我有两个这样的列表:
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
我现在想过滤列表 a,只保留包含列表 b 中的项目。因此,所需的输出如下所示:
[[1,2,3],[2,3,4]]
我尝试了一些嵌套列表推导式,我能想到,但无法获得所需的输出。任何建议都是值得赞赏的。
答:
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)。b
b.isdisjoint(sublist)
isdisjoint
1赞
STerliakov
6/1/2022
@tomerikoo因为这是不必要的工作,所以你真的不需要交叉点——你只想知道这个交叉点是否不是空的。 这里更优化。isdisjoint
0赞
Tomerikoo
6/1/2022
@SUTerliakov 来自文档:“如果集合没有其他元素,则返回 True。当且仅当集合的交集是空集合时,集合才是不相交的。我怀疑运行时存在(关键)差异......
0赞
STerliakov
6/1/2022
@tomerikoo 有趣的是,当我有时间时,我会测量。但是,我想它执行类似于的短路评估,并且会在第一个匹配项目后返回,同时无论如何都会检查整个集合。就像那样不会耗尽迭代器,并且会在第一次之后停止。我真的怀疑这是像这样实现的,它是低效的。isdisjoint
any
False
intersection
any(iterator)
True
isdisjoint
not 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
使用一种方法可以模拟交叉点:set
in
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
评论
[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]