Reputation: 1539
In Python you can do
print (0 or None or False or "" or [] or "hello" or None or "bar")
which will print
hello
Can you do the same with a list? I.e. is there a Python function foo
so that the following will also print hello
?
print (foo([0, None, False, "", [], "hello", None, "bar"]))
Note that bar
is not printed.
Upvotes: 2
Views: 396
Reputation: 17834
You can use the function reduce()
with the operator or
in the lambda
function:
from functools import reduce, partial
foo = partial(reduce, lambda x, y: x or y)
print(foo([0, None, False, "", [], "hello", None, "bar"]))
# hello
Upvotes: 0
Reputation: 1123002
You can use next(filter(None, ...))
or next(filter(bool, ...))
to find the first truthy value from a list:
def foo(l):
return next(filter(None, l))
The filter()
function takes both a filter function, and an iterable, and returns an iterator that of the values from the iterable that pass the filter.
But when you set the filter function to None
, then it is essentially the same thing as using bool
as the filter function, so only values that are true are allowed through. The next()
function then gives you the first such value.
Demo:
>>> def foo(l):
... return next(filter(None, l))
...
>>> print(foo([0, None, False, "", [], "hello", None, "bar"]))
hello
You may want to add the last value in l
as a default for the next()
call, in case there are only falsey values; v1 or v2 or v3 or v4
would at least produce v4
if none of the values are truthy, so the following does too:
def foo(l):
return next(filter(None, l), l[-1])
Using filter(None, ...)
is a fraction faster than filter(bool, ...)
because the filter.__next__
implementation tests for None
before it tests for bool
; this speed difference is very small and barely measurable (within a margin of error):
>>> import timeit
>>> import random
>>> t = [random.choice([True, False]) for _ in range(10 ** 6)]
>>> for ff in ('bool', 'None'):
... count, total = timeit.Timer(f'deque(filter({ff}, t), maxlen=0)', 'from collections import deque; from __main__ import t').autorange()
... print(f"{ff}: {total / count * 1000:8.4f} ms")
...
bool: 98.9971 ms
None: 95.7907 ms
Upvotes: 6