将数字列表乘以一段数字范围

4

我正在尝试编写模11代码,但我无法使它更像Python。

目前,我使用一个权重并增加它,检查当它达到一个数字时,然后将其设置为其原始值。

假设我有一个数字列表1..20,我想将它们乘以2,3,4,5,6,7,8,9,2,3,4等,以便每个索引都乘以递增的数字。

1x2,2x3,3x4,4x5,5x6,6x7,7x8,8x9,9x2,10x3等。

有没有一种优雅的方法来实现这个?

不太优雅的方法:

def mod11(list, max_weight=9):
    sum = 0
    weight = 2

    for item in reversed(list):
        sum += item * weight
        weight += 1

        if weight > max_weight:
            weight = 2

    mod = 11 - sum % 11

    if mod > 9:
        return 0

    else:
        return mod

2
那么你的“不太优雅”的方法是什么?你需要展示一下你已经尝试过什么,以及哪些没有起作用。 - Anzel
1
我认为最优雅的方法是使用列表推导式 - Ozgur Vatansever
@ozgur,是的,我正在考虑这个问题,但我不确定如何重置乘数。 - Onilol
3
你可能想要查看itertools.cycle。提示:使用*cycle(range(2,max_weight + 1))*。 - Ozgur Vatansever
6个回答

2

您可以使用当前索引来确定乘数:

>>> [(index % 8 + 2) * item for index, item in enumerate(range(1, 21))]
[2, 6, 12, 20, 30, 42, 56, 72, 18, 30, 44, 60, 78, 98, 120, 144, 34, 54, 76, 100]
#^        resets               ^            resets               ^

或者,您可以使用"cycle"函数来循环乘数序列,并将其与输入序列一起压缩:
>>> from itertools import cycle
>>> [x * y for x, y in zip(range(1, 21), cycle(range(2, 10)))]
[2, 6, 12, 20, 30, 42, 56, 72, 18, 30, 44, 60, 78, 98, 120, 144, 34, 54, 76, 100]

你是怎么想出那个模数计算的?太聪明了! - Onilol

1

好的,我不太确定我是否正确理解了你的问题,因为你谈到了模数11,但似乎也使用了从2到9的数字。

但让我们首先将1..20写成列表,可以按照以下方式进行:

list(range(1,21))    (This is if you want to include the 20)

接下来,将某个整数转换为2到9之间的数字,您可以执行以下操作:

x -> x % 8 + 2

结合这两个,你可以制作一个列表推导式:
[((x-1) % 8 + 2) * x for x in xrange(1,21)]

(-1是为了从2开始而不是从3开始添加的第一个数字)


1
你不必担心重置乘数,如果你使用 itertools.cycle:
>>> itertools.cycle(range(2, 10))
2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, ...

所以你可以像下面这样简化你的函数:
from itertools import cycle

def mod11(lst, max_weight=9):
    multipliers = cycle(range(2, max_weight + 1))
    zipped = zip(lst, multipliers))
    summed = sum(a * b for a, b in zipped)
    mod = 11 - (summed % 11)
    return (0 if mod > 9 else mod)

1

这里已经有很多好的答案了,如果你想使用numpy(通常适用于这种情况),这里提供一种替代方案:

In [1]: import numpy as np

In [2]: a = np.arange(1, 21)  # like range in numpy array

In [3]: a - 1  # calculation performs per element wise... so will a * n
Out[3]:
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19])


In [4]: a * ((a - 1) % 8 + 2)  # directly translate the calculation
Out[4]:
array([  2,   6,  12,  20,  30,  42,  56,  72,  18,  30,  44,  60,  78,
        98, 120, 144,  34,  54,  76, 100])

1
你可以使用itertools中的starmapcycle
首先,创建一个元组列表以进行乘法运算:
>>> from itertools import starmap, cycle
>>> li=zip(range(1,21), cycle(range(2,10)))
>>> li
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 2), (10, 3), (11, 4), (12, 5), (13, 6), (14, 7), (15, 8), (16, 9), (17, 2), (18, 3), (19, 4), (20, 5)]

然后使用starmapmul(来自operator)进行乘法操作:
>>> from operator import mul 
>>> list(starmap(mul, li))
[2, 6, 12, 20, 30, 42, 56, 72, 18, 30, 44, 60, 78, 98, 120, 144, 34, 54, 76, 100]

如果您想要直接理解,可以这样做:
>>> [x*y for x, y in ((e+1, (e%8)+2) for e in range(20))]
[2, 6, 12, 20, 30, 42, 56, 72, 18, 30, 44, 60, 78, 98, 120, 144, 34, 54, 76, 100]

0

可能是一行代码:

s = map(lambda x : x*(x+1),list(range(1,20)))

基本上,map 是用于对表中每个元素执行相同操作的核心函数。第一个参数是将应用于每个元素的函数。如果您想记住生成另一个值用于乘法,可以尝试一些生成器


1
更短的写法:[x * (x + 1) for x in range(1, 20)] - Andrea Corbellini
1
我需要在特定数字后使乘数器重置。 - Onilol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接