【问题标题】:filtering elements from list of lists in Python?从Python列表中过滤元素?
【发布时间】:2011-02-09 00:03:03
【问题描述】:

我想从列表列表中过滤元素,并使用 lambda 迭代每个元素的元素。例如,给定列表:

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) 但这不是重点,想象这些不是数字而是任意元素,我想将它们的值分配给变量名。

【问题讨论】:

    标签: python list list-comprehension


    【解决方案1】:

    试试这样的:

    filter(lambda a: a[0] + a[1] + a[2] >= N, a)
    

    【讨论】:

    • 我想给它们分配变量名,我认为列表索引符号很难阅读并且可能导致错误
    • 如果您关心这个特定示例,请使用sum(a)
    【解决方案2】:

    使用函数代替 lambda,然后使用 myVar = a[0] 等。

    【讨论】:

      【解决方案3】:

      您可以显式命名子列表元素(假设它们的数量总是固定的),方法是给 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 a 的每个元素,即一次 一个 子列表(因此你得到的错误)。通过将 lambda 的参数括在括号中,您是说 lambda 将接收一个参数,但您也命名了它的每个组件。

      【讨论】:

      • 已编辑以扩展解释。
      • 这对我来说似乎仍然比等效的列表理解可读性差很多。
      • 我同意,事实上。我很少喜欢过滤器(或映射,或减少)来列出理解。我只是从这个问题中得知他出于某种原因更喜欢它。编辑:虽然,在这个特定的例子中,我相信它已经足够清楚了......
      • 我倾向于将mapfilter 保留在我已经定义了函数的情况下,这实际上为我节省了一些精力。这个案例不是很清楚或其他什么,但它确实使用了一种有点晦涩的语言特性来解包列表。
      • 有趣的是,我通常发现过滤器使用本身不如解包,我认为这是一个非常好的功能,如 "a, (b, c, d), e = [1, ( 2, 3, 4), 5]
      【解决方案4】:

      你可以这样做

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

      使用解构语法。

      【讨论】:

        【解决方案5】:

        这个怎么样?

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

        我知道,这不是回答所提问题,但它适用于任意长的列表和任意长的子列表,并支持在reduce() 下工作的任何操作。

        【讨论】:

        • reduce(lambda x, y : x + y, b) 的工作原理与sum(b) 几乎相同,但更丑、更长、更难读写。
        • 是的,但它可以推广到任何二进制函数。话虽如此,您的回答更有意义。
        【解决方案6】:

        当我们有其他可用的技术时,将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。)

        当然,您可以在所有 Python 版本中使用赋值样式解包 (def f(item): x, y, z = item; return x + y + z) 和索引 (lambda item: item[0] + item[1] + item[2])。

        【讨论】:

          【解决方案7】:

          好的,显然你知道你可以使用sum。您尝试做的事情的目标似乎有点模糊,但我认为可选参数语法可能会帮助您,或者至少会给您一些启发。如果在参数前放置*,它会创建一个包含自身和所有剩余参数的元组。如果你在它前面加上一个**,你会得到一本字典。

          看到这个:

          def print_test(a,b,c,*d):
              print a
              print b
              print c
              print d
          
          print_test(1,2,3,4,5,6)
          

          打印

          1
          2
          3
          (4, 5, 6)
          

          您也可以将此语法与lambda 一起使用。

          就像我说的,我不确定你到底想做什么,但听起来这可能会有所帮助。我不认为你可以在lambda 中获得局部变量赋值而不进行一些黑客攻击,但也许你可以使用它以某种方式将值分配给变量。

          编辑:啊,我明白你现在正在寻找什么。我想你想要:

          lambda (a, b, c): a+b+c > N
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-12-20
            • 1970-01-01
            • 2014-06-03
            • 2017-10-15
            • 1970-01-01
            • 2023-03-23
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多