在Python中过滤嵌套列表中的元素?

14 投票
7 回答
60602 浏览
提问于 2025-04-15 21:42

我想从一个包含多个列表的列表中筛选出一些元素,并且想用一个简单的函数来遍历每个元素。比如,给定这个列表:

a = [[1,2,3],[4,5,6]]

假设我只想保留那些列表中所有数字的和大于N的元素。我试着写了:

filter(lambda x, y, z: x + y + z >= N, a)

但是我遇到了这个错误:

 <lambda>() takes exactly 3 arguments (1 given)

我该如何在遍历时把每个元素的值分别赋给x、y和z呢?就像zip函数那样,但可以处理任意长度的列表。

谢谢,

补充说明:我知道可以用这个方法来写:filter(lambda x: sum(x)..., a),但这不是我想要的,想象一下这些不是数字,而是任意的元素,我想把它们的值赋给变量名。

7 个回答

1

你可以这样做:

>>> a=[[1,2,3],[4,5,6]]
>>> filter(lambda (x,y,z),: x+y+z>6, a)
[[4, 5, 6]]

这就是使用解构语法。

11

你可以明确地给子列表的元素命名(假设它们的数量是固定的),方法是给lambda一个元组作为参数:

>>> a = [[1,2,3],[4,5,6]]
>>> N = 10
>>> filter(lambda (i, j, k): i + j + k > N, a)
[[4, 5, 6]]

如果你像之前那样指定“lambda i, j, k”,这就意味着lambda会接收三个参数。但是filter会一次给lambda一个元素,也就是一次只给它一个子列表(所以你会遇到错误)。通过把lambda的参数放在括号里,你是在说lambda只会接收一个参数,但同时你也给这个参数的每个部分起了名字。

40

lambdafilter 一起用其实有点傻,因为我们还有其他更好的方法。

在这种情况下,我可能会这样解决这个具体的问题(或者用等效的生成器表达式)

>>> a = [[1, 2, 3], [4, 5, 6]]
>>> [item for item in a if sum(item) > 10]
[[4, 5, 6]]

或者,如果我需要拆包的话,比如

>>> [(x, y, z) for x, y, z in a if (x + y) ** z > 30]
[(4, 5, 6)]

如果我真的需要一个函数,我可以使用参数元组拆包(顺便说一下,这个在 Python 3.x 中被去掉了,因为大家用得不多):lambda (x, y, z): x + y + z 这个写法是把一个元组拆成三个部分,分别是 xyz。(注意,你也可以在 def 中使用这个,比如:def f((x, y, z)): return x + y + z。)

当然,你也可以使用赋值风格的拆包(def f(item): x, y, z = item; return x + y + z)和索引(lambda item: item[0] + item[1] + item[2]),这些在所有版本的 Python 中都可以用。

撰写回答