当第一个元素大于下一个元素时减去列表中的连续元素 - Python
Subtracting consecutive elements in a list when the first element is great than the next - Python
我正在制作一个程序来完成以下内容:
当输入一个列表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)
这段代码感觉有点long/ineffiecient。是否有更好或更多 short/efficient 的方法来做到这一点?
这是我的看法:
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]
另一种替代解决方案:
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)
我正在制作一个程序来完成以下内容:
当输入一个列表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)
这段代码感觉有点long/ineffiecient。是否有更好或更多 short/efficient 的方法来做到这一点?
这是我的看法:
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]
另一种替代解决方案:
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)