【问题标题】:How to get filter to work with a lambda taking multiple arguments?如何让过滤器与带有多个参数的 lambda 一起工作?
【发布时间】:2017-09-28 20:50:47
【问题描述】:

使用 Python,对于需要传递超过 1 个参数的情况,我发现很难让 filter() 与 lambda 一起使用,如下面的 sn-p 中的情况:

max_validation = lambda x,y,z: x < y < z
sequence1 = [1,4,8]
filter(max_validation, sequence1)

它会引发以下错误:

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

请建议这里做错了什么。

【问题讨论】:

  • 您是否要验证它是一个排序列表?

标签: python


【解决方案1】:

要弄清楚你到底想要做什么有点困难。我将解释您的问题,然后提供答案。如果这不正确,请修改您的问题或对此答案发表评论。

问题

我有正好三个元素长的序列。这是一个:

sequence1 = [1, 4, 8]

我想确保第一个元素小于第二个元素,而第二个元素又应该小于第三个元素。为此,我编写了以下函数:

max_validation = lambda x, y, z: x < y < z

如何使用filter 应用它?使用filter(max_validation, sequence1) 不起作用。

回答

Filter 将您的函数应用于提供的可迭代对象的每个元素,如果函数返回 True,则选择它,如果函数返回 False,则丢弃它。

在您的情况下,filter 首先查看值1。它试图将其传递给您的函数。您的函数需要三个参数,但只提供了一个,因此失败。

您需要进行两项更改。首先,将您的三元素序列放入列表或其他序列中。

sequences = [[1, 4, 8], [2, 3, 9], [3, 2, 3]]
max_validation = lambda x: x[0] < x[1] < x[2] and len(x) == 3

我添加了另外两个序列进行测试。因为sequences 是一个列表的列表,所以每个列表都会传递给您的测试函数。即使您只测试一个序列,您也应该使用[[1, 4, 8]],以便将要测试的整个序列传递到您的函数中。

我还修改了max_validation,使其只接受一个参数:要测试的列表。我还添加了and len(x) == 3 以确保序列的长度只有 3 个元素

【讨论】:

  • 超级。你完美地改写了这个问题。答案也很合适。谢谢。
【解决方案2】:

传递给filter() 的函数只得到一个传递给它的参数,即被迭代的可迭代对象中的当前元素。如果您需要比这更高级的东西,那么filter() 不会做。

【讨论】:

    【解决方案3】:

    可以使用闭包来做到这一点:

    >>> def foo(a,b):
    ...   def bar(c):
    ...     return a+b+c
    ...   return bar
    ... 
    >>> x = foo(1,2)
    >>> x(3)
    6
    >>> y = foo(100,0)
    >>> y(1)
    101
    >>> x(1)
    4
    

    【讨论】:

    • 我认为你还没有真正理解 OP 的问题。
    • 嗯?我想我完全理解了。过滤器将一次使用一个 arg 调用该函数。我证明了一种传递额外参数的方法。当然,额外的参数不是来自列表,但这不是过滤器的工作原理。
    【解决方案4】:

    直接来自Python Filters的文档

    注意 filter(function, iterable) 相当于 [item for item in 可迭代 if 函数(项)] 如果 函数不是 None 和 [item for 可迭代中的项目 if item] if 函数 是无。

    因此,您可以只使用 Python 过滤器处理单个参数。这实际上意味着您不能在示例中使用过滤器。您必须为此编写自定义代码。

    【讨论】:

      【解决方案5】:

      希望你知道吗?

      >>> max([1, 4, 8])
      8
      

      filter() 接受一个参数。在你的情况下,需要 1. 然后 4. 然后 8.

      【讨论】:

      • 所呈现的相似性使事情对我来说已经足够明显了。谢谢。
      【解决方案6】:

      这适用于任何长度的序列:

      all(x < y for x, y in zip(seq, seq[1:]))
      

      会发生什么?

      对于序列 1, 2, 3...,您将序列 1, 2, 3... 和 2, 3, 4... 压缩在一起,形成序列 (1, 2), (2, 3) , ... 然后检查语句 'x

      这适用于您要检查的任何关联规则。

      有用的链接:

      1. slices in Python

      2. zip in Python docs

      3. all in Python docs

      【讨论】:

        【解决方案7】:

        我认为所有其他人都没有明白这一点。错误消息是针对 lambda 函数而不是针对过滤器的。你应该这样称呼它:

        filter(max_validation, *sequence1)
        

        在列表中添加一个星号将其转换为三个参数,然后它将起作用。

        【讨论】:

        • 如果我尝试这样做,我会得到TypeError: filter expected 2 arguments, got 4
        • 抱歉打扰了,我没有仔细阅读。那么卫斯理的回答很好。
        【解决方案8】:

        我同意@walkingpendulum 和@Wesley,这取决于对实际问题陈述的解释。所以通过问题陈述中的歧义来解析: 如果您在可迭代对象中按顺序将一个项目与其先前的值进行比较,则 lambda 表达式是矫枉过正的,只是 使用列表推导:

        [1 if i < i+1 else 0 for i in sequence1]
        

        如果您要比较对象,那么只需比较它们——lambda 表达式首先不起作用,因为您只传递一个参数,而您定义的 lambda 表达式传递三个参数,而 lambda 通常应用于一个可迭代对象。为了比较对象,有一些简单的结构:

        sequence1 == some_other_sequence
        

        x, y, z = 1, 2, 3
        x < y < z
        

        最后,如果您想将 lambda 表达式应用于可迭代对象,map 可以帮助您:(任意 lambda 函数)

        map(lambda x: x > 1, sequence1)
        

        否则@walkingpendulum 和@Wesley 涵盖其他解释

        【讨论】:

          【解决方案9】:

          你可以改变

          max_validation = lambda x,y,z: x < y < z
          

          max_validation = lambda (x,y,z): x < y < z
          

          【讨论】:

          • 文件“”,第 1 行 max_validation = lambda (x,y,z): x
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-12-08
          • 1970-01-01
          • 1970-01-01
          • 2018-01-12
          • 2018-02-11
          • 1970-01-01
          相关资源
          最近更新 更多