【问题标题】:How to use the IF ALL statement in Python [duplicate]如何在 Python 中使用 IF ALL 语句 [重复]
【发布时间】:2018-07-29 20:31:38
【问题描述】:

我有一个名为 checker(nums) 的函数,它有一个参数,稍后将接收一个列表。我想对该列表做的是检查每个其他元素是否大于或等于前一个元素。 例子: 我有一个列表[1, 1, 2, 2, 3],我必须检查它是否满足条件。 既然这样,函数应该返回True

我的代码:

def checker(nums):
    for x in range(len(nums)):
        if x+1<len(nums):
            if nums[x] <= nums[x+1] and nums[-1] >= nums[-2]:
                return True

如果第一个条件为真,这只会运行一次并返回 True。 我看过一个声明 if all 并且不确定如何使用它。

【问题讨论】:

    标签: python list sorting if-statement conditional-statements


    【解决方案1】:

    您的功能可以简化为:

    def checker(nums):
        return all(i <= j for i, j in zip(nums, nums[1:]))
    

    注意以下几点:

    • zip 并行循环其参数,即检索nums[0]nums[1],然后检索nums[1]nums[2] 等。
    • i &lt;= j 执行实际比较。
    • 由括号 () 表示的 generator expression 确保条件的每个值,即 TrueFalse 一次提取一个。这称为惰性求值
    • all 只是检查所有值都是True。同样,这是懒惰的。如果从生成器表达式中延迟提取的值之一是False,它会短路并返回False

    替代方案

    为避免为zip 的第二个参数构建列表的开销,您可以使用itertools.islice。当您的输入是迭代器时,此选项特别有用,即它不能像 list 那样被切片。

    from itertools import islice
    
    def checker(nums):
        return all(i <= j for i, j in zip(nums, islice(nums, 1, None)))
    

    另一个对迭代器友好的选项是使用itertools pairwise recipe,也可以通过第三方more_itertools.pairwise 获得:

    # from more_itertools import pairwise  # 3rd party library alternative
    from itertools import tee
    
    def pairwise(iterable):
        "s -> (s0,s1), (s1,s2), (s2, s3), ..."
        a, b = tee(iterable)
        next(b, None)
        return zip(a, b)
    
    def checker(nums):
        return all(i <= j for i, j in pairwise(nums))
    

    另一种选择是使用函数式方法而不是推导式:

    from operator import le
    
    def checker_functional(nums):
        return all(map(le, nums, nums[1:]))
    

    【讨论】:

      【解决方案2】:

      您的代码实际上可以简化为检查 nums 是否已排序,例如

      def checker(nums):
          return sorted(nums) == nums
      

      这完全符合您的预期,例如

      >>> checker([1, 1, 2, 2, 3])
      True
      >>> checker([1, 1, 2, 2, 1])
      False
      

      【讨论】:

      • 缺点是这个解决方案是 O(N log N)。优点是简单
      • 这只是部分正确。如果列表是排序的,这实际上只是 O(n),参见例如stackoverflow.com/questions/23809785/…。但可以肯定的是,最坏情况的复杂度是 O(n log n)。
      • 你错了,这不是“部分正确”,我只提到了最坏情况。我从来没有谈论过最好的情况或一般的情况。如果我在谈论最好的情况,我会使用正确的符号。而我们之所以做这个检查是因为有时候列表没有排序,所以是O(N log N)
      【解决方案3】:

      使用more_itertools.windowed@jp_data_analysis 的类似解决方案

      >>> from more_itertools import windowed
      >>> nums = [1, 1, 2, 2, 3]
      >>> all(i <= j for i, j in windowed(nums, 2))
      True
      

      出于科学目的(不推荐代码),这里有一个更实用的方法

      >>> from operator import le
      >>> from itertools import starmap
      >>> all(starmap(le, windowed(nums, 2)))
      True
      

      【讨论】:

        猜你喜欢
        • 2018-07-06
        • 1970-01-01
        • 2020-04-16
        • 1970-01-01
        • 2015-01-26
        • 2013-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多