emissions=[30,50,20,70]
f=[0,30,30,80,80,100,100,160)
such as:
f=[]
f[1]=emissions[0]
f[2]=emissions[0]
f[3]=emissions[0]+emissions[1]
f[4]=emissions[0]+emissions[1]
f[5]=emissions[0]+emissions[1]+emissions[2]
f[6]=emissions[0]+emissions[1]+emissions[2]
f[7]=emissions[0]+emissions[1]+emissions[2]+emissions[3]
Я считаю, что ответ должен учитывать какой-то цикл, но я не могу понять, как
Используйте numpy.cumsum с добавлением 0
, numpy.repeat с удалением первого и последнего повторяющихся значений путем индексации, если в больших списках важна производительность:
f = np.repeat(np.cumsum([0] + emissions), 2)[1:-1].tolist()
print (f)
[0, 30, 30, 80, 80, 100, 100, 170]
np.random.seed(123)
emissions = np.random.randint(100, size=1000).tolist()
In [107]: %%timeit
...: np.repeat(np.cumsum([0] + emissions), 2)[1:-1].tolist()
...:
...:
149 µs ± 13.8 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [108]: %%timeit
...: cumsum = [0] + list(accumulate(emissions))
...: f = [x for pair in zip(cumsum, cumsum[1:]) for x in pair]
...:
...:
192 µs ± 14.1 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Чистым подходом Python было бы использование accummulate :
from itertools import accumulate
emissions = [30, 50, 20, 70]
cumsum = [0] + list(accumulate(emissions))
f = [x for pair in zip(cumsum, cumsum[1:]) for x in pair]
#[0, 30, 30, 80, 80, 100, 100, 170]
С itertools:
from itertools import accumulate, pairwise, chain
emissions = [30, 50, 20, 70]
f = [*chain(*pairwise([0, *accumulate(emissions)]))]
print(f)
Без:
s = 0
f = []
for e in emissions:
f += s, (s := s + e)
print(f)
Тест со случайными списками длиной 1000 (например, jezrael):
100.69 ± 0.99 μs Kelly1c
108.02 ± 1.19 μs Kelly2
108.22 ± 1.72 μs Kelly1b
109.11 ± 1.70 μs jezrael
112.12 ± 1.23 μs Kelly1
140.18 ± 1.35 μs Timeless
Контрольный код (Попробуйте онлайн!):
import numpy as np
from itertools import accumulate, pairwise, chain
from timeit import timeit
from statistics import mean, stdev
def Kelly1(emissions):
return [*chain(*pairwise([0, *accumulate(emissions)]))]
def Kelly1b(emissions):
return [*chain.from_iterable(pairwise([0, *accumulate(emissions)]))]
def Kelly1c(emissions):
return [*chain.from_iterable(pairwise(accumulate(emissions, initial=0)))]
def Kelly2(emissions):
s = 0
f = []
for e in emissions:
f += s, (s := s + e)
return f
def Timeless(emissions):
cumsum = [0] + list(accumulate(emissions))
return [x for pair in zip(cumsum, cumsum[1:]) for x in pair]
def jezrael(emissions):
return np.repeat(np.cumsum([0] + emissions), 2)[1:-1].tolist()
funcs = Kelly1, Kelly1b, Kelly1c, Kelly2, Timeless, jezrael
emissions = [30, 50, 20, 70]
for f in funcs:
print(f(emissions))
times = {f: [] for f in funcs}
def stats(f):
ts = [t * 1e6 for t in sorted(times[f])[:10]]
return f'{mean(ts):6.2f} ± {stdev(ts):4.2f} μs '
np.random.seed(123)
for _ in range(100):
emissions = np.random.randint(100, size=1000).tolist()
for f in funcs:
t = timeit(lambda: f(emissions), number=100) / 100
times[f].append(t)
for f in sorted(funcs, key=stats):
print(stats(f), f.__name__)
Какое это имеет отношение к мин/макс? Вы просто добавляете.