在Python中过滤嵌套列表中的元素?
我想从一个包含多个列表的列表中筛选出一些元素,并且想用一个简单的函数来遍历每个元素。比如,给定这个列表:
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 个回答
你可以这样做:
>>> a=[[1,2,3],[4,5,6]]
>>> filter(lambda (x,y,z),: x+y+z>6, a)
[[4, 5, 6]]
这就是使用解构语法。
你可以明确地给子列表的元素命名(假设它们的数量是固定的),方法是给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只会接收一个参数,但同时你也给这个参数的每个部分起了名字。
用 lambda
和 filter
一起用其实有点傻,因为我们还有其他更好的方法。
在这种情况下,我可能会这样解决这个具体的问题(或者用等效的生成器表达式)
>>> 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
这个写法是把一个元组拆成三个部分,分别是 x
、y
和 z
。(注意,你也可以在 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 中都可以用。