How to use the IF ALL statement in Python
Your code can in fact be reduced to checking if nums
is sorted, e.g.
def checker(nums):
return sorted(nums) == nums
This does exactly what you expect, e.g.
>>> checker([1, 1, 2, 2, 3])
True
>>> checker([1, 1, 2, 2, 1])
False
Your function can be reduced to this:
def checker(nums):
return all(i <= j for i, j in zip(nums, nums[1:]))
Note the following:
zip
loops through its arguments in parallel, i.e.nums[0]
&nums[1]
are retrieved, thennums[1]
&nums[2]
etc.i <= j
performs the actual comparison.- The generator expression denoted by parentheses
()
ensures that each value of the condition, i.e.True
orFalse
is extracted one at a time. This is called lazy evaluation. all
simply checks all the values areTrue
. Again, this is lazy. If one of the values extracted lazily from the generator expression isFalse
, it short-circuits and returnsFalse
.
Alternatives
To avoid the expense of building a list for the second argument of zip
, you can use itertools.islice
. This option is particularly useful when your input is an iterator, i.e. it cannot be sliced like a list
.
from itertools import islice
def checker(nums):
return all(i <= j for i, j in zip(nums, islice(nums, 1, None)))
Another iterator-friendly option is to use the itertools
pairwise
recipe, also available via 3rd party 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))
Another alternative is to use a functional approach instead of a comprehension:
from operator import le
def checker_functional(nums):
return all(map(le, nums, nums[1:]))