首页 > 解决方案 > 如何在不同长度的列表上使用 map(),用自定义值填充最短的列表

问题描述

我想使用地图在多个列表上应用一个函数,并用自定义值填充最短的列表。我已经使用 for 循环和 zip_longest 创建了一个解决方案,但我认为可以使用map(). 我不知道哪个列表最长,它们可能具有相同的长度。这是我的实现:

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))

的价值squared_numbers

[1, 4, 1.2000000000000002, 0.48]

奖励:我更喜欢通过 设置自定义值def multiply(a=5, b=0.4, c=0.3),但我不确定这是否可行。

编辑:代码工作正常,我只是好奇它是否可以进一步优化。

标签: python

解决方案


也许你的意思是itertools.starmap而不是map?这是我想出的东西,但我不会说它比你已经写的更好:

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)

输出:

[1, 4, 1.2000000000000002, 0.48]
>>> 

如果您正在使用itertools.zip_longest,则无法真正绕过使用fillvalue- 在我们的例子中,这意味着我们将始终将三个参数传递给multiply,即使它们全部或其中一些是None(itertools.zip_longest的默认值fillvalue)。这意味着您不能使用默认的位置参数,因为它们只有在没有足够的位置参数传入时才会生效,而永远不会出现这种情况。

中的生成器表达式functools.reduce通过短路评估工作。该表达式arg or default将评估arg是否arg为真,default否则。None被认为是错误的,因此如果argNone,则表达式的计算结果为default


推荐阅读