2013-04-08 3 views
41
time_interval = [4, 6, 12] 

Я хочу подытожить цифры [4, 4+6, 4+6+12], чтобы получить список t = [4, 10, 22].Как найти суммарную сумму чисел в списке?

Я попытался следующие:

for i in time_interval: 
    t1 = time_interval[0] 
    t2 = time_interval[1] + t1 
    t3 = time_interval[2] + t2 
    print(t1, t2, t3) 

4 10 22 
4 10 22 
4 10 22 
+11

Примечание: не вызывайте список «list». Это имя встроенной функции, используемой для преобразования других вещей в списки, и вы не хотите скрывать это. – abarnert

+0

См. Также http://stackoverflow.com/q/9258602 – hpaulj

ответ

-8

В ответ на первоначальный вопрос с вопросом, как «суммировать числа в списке»: Проверьте встроенную функцию сумма(), он, вероятно, делает то, что вы хотеть.

+0

Не совсем; ему нужно превратить последовательность в серию. – abarnert

+0

Может быть. Мой хрустальный шар (tm) недостаточно хорош, чтобы сказать это с уверенностью. ;) –

+7

Ну, он дает ожидаемый результат, '[4, 10, 22]', поэтому вам не нужен хрустальный шар, чтобы знать, что '22' - неправильный ответ. – abarnert

56

В Python 2 вы можете определить свою собственную функцию генератора, как это:

def accumu(lis): 
    total = 0 
    for x in lis: 
     total += x 
     yield total 

In [4]: list(accumu([4,6,12])) 
Out[4]: [4, 10, 22] 

И в Python 3.2+ вы можете использовать itertools.accumulate():

In [1]: lis = [4,6,12] 

In [2]: from itertools import accumulate 

In [3]: list(accumulate(lis)) 
Out[3]: [4, 10, 22] 
1

Во-первых, вы хотите, пополняемый список подпоследовательности :

subseqs = (seq[:i] for i in range(1, len(seq)+1)) 

Тогда вы просто позвоните sum по eac ч подпоследовательности:

sums = [sum(subseq) for subseq in subseqs] 

(Это не самый эффективный способ сделать это, потому что вы добавляете все префиксы повторно. Но это, вероятно, не будет иметь большого значения для большинства случаев использования, и это легче понять, если вам не нужно думать о текущих итогах.)

Если вы используете Python 3.2 или новее, вы можете использовать itertools.accumulate сделать это для вас:

sums = itertools.accumulate(seq) 

и если вы используете 3.1 или выше, вы можете просто скопировать «эквивалент» источник прямо из документации (для изменения next(it) в it.next() за 2,5 и выше, за исключением).

+7

Это работает в квадратичном времени (возможно, это не имеет значения для OP, но стоит упомянуть). –

+0

Во-первых, когда N = 3, кто заботится о квадратичном времени? И я не думаю, что это слишком сложно. Это два очень простых шага, каждый из которых превращает один итератор в другой, непосредственно переводя описание на английском языке. (Тот факт, что он использует необычный способ определения серий, где префикс 0-длины не учитывается, делает его несколько более сложным ... но это неотъемлемо от проблемы, и я подумал, что лучше положить это в 'range', чем взломать его, сделав' [1:] 'в конце или проигнорировать его.) – abarnert

+0

Предположительно, фактическая проблема OP состоит в том, чтобы не получить частичные суммы' [4,6,12] ' поскольку, как он писал в вопросе, он уже знает, что это такое! –

2

Попробуйте это: (? Большие списки)

result = [] 
acc = 0 
for i in time_interval: 
    acc += i 
    result.append(acc) 
2
values = [4, 6, 12] 
total = 0 
sums = [] 

for v in values: 
    total = total + v 
    sums.append(total) 

print 'Values: ', values 
print 'Sums: ', sums 

Выполнение этого кода дает

Values: [4, 6, 12] 
Sums: [4, 10, 22] 
1
lst = [4,6,12] 

[sum(lst[:i+1]) for i in xrange(len(lst))] 

Если вы ищете более эффективного решения генератор может быть хороший вызов (или просто используйте numpy, если вы действительно заботитесь о перфомансе).

def gen(lst): 
    acu = 0 
    for num in lst: 
     yield num + acu 
     acu += num 

print list(gen([4, 6, 12])) 
0
In [42]: a = [4, 6, 12] 

In [43]: [sum(a[:i+1]) for i in xrange(len(a))] 
Out[43]: [4, 10, 22] 

Это slighlty быстрее, чем метод генератора выше по @Ashwini для небольших списков

In [48]: %timeit list(accumu([4,6,12])) 
    100000 loops, best of 3: 2.63 us per loop 

In [49]: %timeit [sum(a[:i+1]) for i in xrange(len(a))] 
    100000 loops, best of 3: 2.46 us per loop 

Для больших списков, генератор является путь наверняка. , ,

In [50]: a = range(1000) 

In [51]: %timeit [sum(a[:i+1]) for i in xrange(len(a))] 
    100 loops, best of 3: 6.04 ms per loop 

In [52]: %timeit list(accumu(a)) 
    10000 loops, best of 3: 162 us per loop 
+1

Вы выбираете только 3 списка предметов, попробуйте 10^4 предметов. –

+1

Правда, для больших списков генератор намного быстрее! – reptilicus

+0

Я отредактировал свой ответ, чтобы показать это. – reptilicus

62

Если вы делаете много численной работы с массивами, как это, я хотел бы предложить numpy, который поставляется с кумулятивной функцией суммы cumsum:

import numpy as np 

a = [4,6,12] 

np.cumsum(a) 
#array([4, 10, 22]) 

Numpy часто быстрее, чем чистый питон для такого рода вещи, увидеть в сравнении с @Ashwini's accumu:

In [136]: timeit list(accumu(range(1000))) 
10000 loops, best of 3: 161 us per loop 

In [137]: timeit list(accumu(xrange(1000))) 
10000 loops, best of 3: 147 us per loop 

In [138]: timeit np.cumsum(np.arange(1000)) 
100000 loops, best of 3: 10.1 us per loop 

Но, конечно, если это единственное место, где вы будете использовать NumPy, он не может быть ш ор, имеющей зависимость от него.

+1

У этого должен быть случай «np.cumsun», который начинается со списка, чтобы учесть время преобразования. – hpaulj

+2

Хорошая точка @hpaulj, для тех, кто начинает (или стремится) к 'списку', я бы не рекомендовал' numpy'. – askewchan

+0

Я не думаю, что numpy является самым быстрым http://stackoverflow.com/questions/15889131/how-to-find-the-cumulative-sum-of-numbers-in-a-list/39534850#39534850 –

0

Несколько Hacky, но, кажется, работает:

def cumulative_sum(l): 
    y = [0] 
    def inc(n): 
    y[0] += n 
    return y[0] 
    return [inc(x) for x in l] 

Я думаю, что внутренняя функция будет иметь возможность изменить y объявленный во внешней лексической области, но это не сработало, так что мы играем некоторые неприятные хаки с модификацией структуры. Возможно, более изящно использовать генератор.

0

Без использования Numpy вы можете прокручивать непосредственно по массиву и накапливать сумму по пути. Например:

a=range(10) 
i=1 
while((i>0) & (i<10)): 
    a[i]=a[i-1]+a[i] 
    i=i+1 
print a 

Результаты в:

[0, 1, 3, 6, 10, 15, 21, 28, 36, 45] 
10

Behold:

a = [4, 6, 12] 
reduce(lambda c, x: c + [c[-1] + x], a, [0])[1:] 

будет выводить (как ожидалось):

[4, 10, 22] 
+0

Отличный ответ и эффективный! –

+6

* Не * эффективный. Суммарная стоимость выполнения 'c + [c [-1] + x]' снова и снова добавляет к общей квадратичной времени выполнения во входной длине. – user2357112

+0

сокращение полезно для единовременной совокупной суммы, но если вы выполняете много вызовов функции cumsum, генератор будет полезен для «предварительной обработки» ваших значений cumulative_sum и доступа к ним в O (1) для каждого последующего вызова , –

0
def cummul_sum(list_arguement): 
    cumm_sum_lst = [] 
    cumm_val = 0 
    for eachitem in list_arguement: 
     cumm_val += eachitem 
     cumm_sum_lst.append(cumm_val) 
    return cumm_sum_lst 
-1

Т его будет Haskell стиль:

def wrand(vtlg): 

    def helpf(lalt,lneu): 

     if not lalt==[]: 
      return helpf(lalt[1::],[lalt[0]+lneu[0]]+lneu) 
     else: 
      lneu.reverse() 
      return lneu[1:]   

    return helpf(vtlg,[0]) 
5

я сделал скамью-начертание двух верхних ответов с Python 3.4 и я нашел itertools.accumulate быстрее, чем numpy.cumsum при многих обстоятельствах, часто гораздо быстрее. Однако, как вы можете видеть из комментариев, это может быть не всегда так, и трудно исчерпывающе изучить все варианты. (Не стесняйтесь добавить комментарий или отредактировать этот пост, если у вас есть дополнительные результаты для сравнения.)

Некоторые тайминги ...

Для коротких списков accumulate составляет около 4 раза быстрее:

from timeit import timeit 

def sum1(l): 
    from itertools import accumulate 
    return list(accumulate(l)) 

def sum2(l): 
    from numpy import cumsum 
    return list(cumsum(l)) 

l = [1, 2, 3, 4, 5] 

timeit(lambda: sum1(l), number=100000) 
# 0.4243644131347537 
timeit(lambda: sum2(l), number=100000) 
# 1.7077815784141421 

Для более длинных списков accumulate около 3 раза быстрее:

l = [1, 2, 3, 4, 5]*1000 
timeit(lambda: sum1(l), number=100000) 
# 19.174508565105498 
timeit(lambda: sum2(l), number=100000) 
# 61.871223849244416 

Если numpyarray не приводится к list, accumulate является еще примерно в 2 раза быстрее:

from timeit import timeit 

def sum1(l): 
    from itertools import accumulate 
    return list(accumulate(l)) 

def sum2(l): 
    from numpy import cumsum 
    return cumsum(l) 

l = [1, 2, 3, 4, 5]*1000 

print(timeit(lambda: sum1(l), number=100000)) 
# 19.18597290944308 
print(timeit(lambda: sum2(l), number=100000)) 
# 37.759664884768426 

Если поставить импорт за пределами этих двух функций и по-прежнему возвращают numpyarray, accumulate еще почти в 2 раза быстрее:

from timeit import timeit 
from itertools import accumulate 
from numpy import cumsum 

def sum1(l): 
    return list(accumulate(l)) 

def sum2(l): 
    return cumsum(l) 

l = [1, 2, 3, 4, 5]*1000 

timeit(lambda: sum1(l), number=100000) 
# 19.042188624851406 
timeit(lambda: sum2(l), number=100000) 
# 35.17324400227517 
+4

Вы не ожидали бы, что самолет будет быстрее, чем поезд, чтобы путешествовать по городу, особенно включая покупку билетов и проверку безопасности. Точно так же вы не будете использовать numpy для обработки «списка» из пяти элементов, особенно если вы не хотите принимать «массив» взамен. Если список, о котором идет речь, действительно настолько короток, то их время работы будет _инсексуальным _---зависимостями и удобочитаемостью, несомненно, будет доминировать. Но широкое использование «списка» однородного числового типа данных значительной длины было бы глупо; для этого, numpy 'array' _would_ будет подходящим и обычно быстрее. – askewchan

+0

@askewchan Я не просто нашел это для коротких списков, и вопрос OP запрашивает список как вывод, а не массив numpy. Возможно, вы можете отредактировать свой ответ, чтобы быть более четким, когда каждое использование подходит :) –

+0

@askewchan На самом деле я отредактировал свой ответ с гораздо более подробным сравнением. Ни при каких обстоятельствах я не нахожу «numpy» быстрее, если я не упустил что-то? –

2

Если Вы хотите вещий путь без NumPy, работающих в 2.7 это будет мой способ сделать это

l = [1,2,3,4] 
_d={-1:0} 
cumsum=[_d.setdefault(idx, _d[idx-1]+item) for idx,item in enumerate(l)] 

теперь давайте попробуем и проверить его от всех других реализаций

import timeit 
L=range(10000) 

def sum1(l): 
    cumsum=[] 
    total = 0 
    for v in l: 
     total += v 
     cumsum.append(total) 
    return cumsum 


def sum2(l): 
    import numpy as np 
    return list(np.cumsum(l)) 

def sum3(l): 
    return [sum(l[:i+1]) for i in xrange(len(l))] 

def sum4(l): 
    return reduce(lambda c, x: c + [c[-1] + x], l, [0])[1:] 

def this_implementation(l): 
    _d={-1:0} 
    return [_d.setdefault(idx, _d[idx-1]+item) for idx,item in enumerate(l)] 


# sanity check 
sum1(L)==sum2(L)==sum3(L)==sum4(L)==this_implementation(L) 
>>> True  

# PERFORMANCE TEST 
timeit.timeit('sum1(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100. 
>>> 0.001018061637878418 

timeit.timeit('sum2(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100. 
>>> 0.000829620361328125 

timeit.timeit('sum3(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100. 
>>> 0.4606760001182556 

timeit.timeit('sum4(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100. 
>>> 0.18932826995849608 

timeit.timeit('this_implementation(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100. 
>>> 0.002348129749298096 
Смежные вопросы