【问题标题】:Subtracting consecutive elements in a list when the first element is great than the next - Python当第一个元素大于下一个元素时,减去列表中的连续元素 - Python
【发布时间】:2019-01-08 07:48:11
【问题描述】:

我正在制作一个完成以下内容的程序:

当输入一个列表a时,如果结果是非负数,它将减去连续的元素(从头开始)。 例如,如果

a=[3,2,1]

然后连续的数字将被减去,所以a=[1,1],然后是a=[0]。此外,在结果中,所有数字都必须升序(例如,2,1 不能在列表中)。另一个例子:

a=[1, 10, 7, 3, 2]
[1, 3, 3, 2] #10-7 (10 and 7 get replaced with 3)
[1, 0, 2]    #3-3  (precedence goes to the left: 3-3 gets subtracted, not 3-2)
[1, 2]       #1-0

这是我当前的代码(其中 a 是随机生成的):

import random
a=[random.randint(1,10) for e in range(20)]
print(a)
loop=1
while True:
    try:
        #print(loop,a)
        subloop=0
        while subloop<loop:
            if a[loop-subloop]<=a[loop-1-subloop]:
                a[loop-1-subloop]=a[loop-1-subloop]-a.pop(loop-subloop)
                if loop!=1:
                    loop-=1
            subloop+=1
        if a[loop]<=a[loop-1]:
            a[loop-1]=a[loop-1]-a.pop(loop)
        else:
            loop+=1
    except IndexError:
        break
print(a)

这段代码感觉有点长/效率低。有没有更好或更短/更有效的方法来做到这一点?

【问题讨论】:

  • 第一个示例不应该以[0] 结尾吗? [3, 2, 1] -> [1, 1] -> [0]
  • 是的。很抱歉
  • 在你的例子中,你为什么不做10-73-2?每次迭代只有一个减法吗?
  • 即使你这样做了,它是否仍然以[1,2] 结束。我不确定它是否会有所作为

标签: python list performance loops subtraction


【解决方案1】:

这是我的看法:

a = [1, 10, 7, 3, 2]
b = [3, 2, 1]


def index_helper(l):
    for i, x in enumerate(l[:-1]):
        if l[i] >= l[i+1]:
            return i


def reduce(l):
    i = index_helper(l)
    while i is not None:
        l[i:i + 2] = [l[i] - l[i + 1]]
        i = index_helper(l)
    return l


>>> reduce(a)
[1, 2]

>>> reduce(b)
[0]

【讨论】:

    【解决方案2】:

    另一种替代解决方案:

    def my_func(a):
        next_i = next((i for i in range(len(a)-1) if (a[i] - a[i+1]) >=0), None)
        while next_i is not None:
            a = a[:next_i] + [a[next_i] - a[next_i+1]] + a[next_i+2:]
            next_i = next((i for i in range(len(a)-1) if (a[i] - a[i+1]) >=0), None)
        return a
    
    print(my_func(a=[1, 10, 7, 3, 2]))
    #[1, 2]
    
    print(my_func(a=[3, 2, 1]))
    #[0]
    

    不过,这比@bphi 的解决方案要慢一些:

    import random
    N = 10000
    a_list = [[random.randint(1,10) for e in range(20)] for _ in range(N)]
    
    all([reduce(l) == my_func(l) for l in a_list])  # verify answers are same
    #True
    
    %%timeit
    [my_func(l) for l in a_list]
    #10.7 ms ± 358 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    
    %%timeit
    [reduce(l) for l in a_list]
    #7.51 ms ± 416 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    

    【讨论】:

      猜你喜欢
      • 2015-12-16
      • 1970-01-01
      • 2019-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-04
      • 1970-01-01
      • 2013-09-25
      相关资源
      最近更新 更多