I want to apply a function on multiple lists using map, and fill the shortest list(s) with a custom value. I have created a solution using a for loop and zip_longest but I think it could be improved using map()
. I’m unaware which of the list(s) is the longest, they could have equal lengths. Here’s my implementation:
import itertools items1 = [1, 2, 3, 4] items2 = [1, 2] items3 = [1, 1, 1] def multiply(a, b, c): if a is None: a = 0.5 # custom value, could also be set elsewhere if b is None: b = 0.4 if c is None: c = 0.3 return a * b * c squared_numbers = [] for numbers in itertools.zip_longest(items1, items2, items3): squared_numbers.append(multiply(*numbers))
Value of squared_numbers
:
[1, 4, 1.2000000000000002, 0.48]
Bonus: I prefer to set the custom values via def multiply(a=5, b=0.4, c=0.3)
, but I’m not sure if this is possible.
EDIT: The code works fine, I’m just curious if it can be optimized further.
Advertisement
Answer
Maybe you meant itertools.starmap
instead of map
? Here’s something I came up with but I wouldn’t really say it’s better than what you’ve already written:
from itertools import zip_longest, starmap lists = [ [1, 2, 3, 4], [1, 2], [1, 1, 1] ] def multiply(*args): from functools import reduce from operator import mul defaults = [0.5, 0.4, 0.3] return reduce(mul, (arg or default for arg, default in zip(args, defaults))) squared_numbers = list(starmap(multiply, zip_longest(*lists))) print(squared_numbers)
Output:
[1, 4, 1.2000000000000002, 0.48] >>>
If you’re using itertools.zip_longest
, you can’t really get around using a fillvalue
– in our case that means we will always pass three arguments to multiply
, even if all- or some of them are None
(itertools.zip_longest
‘s default fillvalue
). This means you can’t use default positional-arguments, because they only take effect when not enough positional-arguments are passed in, which will never be the case.
The generator expression in functools.reduce
works through short-circuit evaluation. The expression arg or default
will evaluate to arg
if arg
is truthy, and default
otherwise. None
is considered falsey, so if arg
is None
, the expression evaluates to default
.