基于索引列表的列表中的累加

时间:2018-11-07 14:37:17

标签: python python-2.7 numpy

说我有清单,list_a = [100, 5, 1, 2, 200, 3, 1, 300, 6, 6]

还有另一个列表,ind_list = [0, 4, 7]

我想创建第三个列表,其中包含第一个列表的累积总和,该列表“重设”来自ind_list的每个索引。

为澄清起见,结果应为res_list = [100, 105, 106, 108, 200, 203, 204, 300, 306, 312]

8 个答案:

答案 0 :(得分:9)

使用以下内容:

cs= np.cumsum(list_a)
for i in ind_list:
    if i==0:
        continue
    cs[i:]-=cs[i-1]

结果:

cs
>>array([100, 105, 106, 108, 200, 203, 204, 300, 306, 312])

答案 1 :(得分:4)

itertools人需要救援:

from itertools import accumulate as acc, chain

list_a = [100, 5, 1, 2, 200, 3, 1, 300, 6, 6]
ind_list = [0, 4, 7]

list(chain(*(acc(list_a[x:y]) for x, y in zip(ind_list, ind_list[1:]+[None]))))
# [100, 105, 106, 108, 200, 203, 204, 300, 306, 312]

答案 2 :(得分:3)

它是NumPy标记的,找到矢量化解决方案很有趣,所以这里是一个-

def intervaled_cumsum(list_a, ind_list):
    a = np.array(list_a)
    a[ind_list[1:]] -= np.add.reduceat(a,ind_list)[:-1]
    return a.cumsum()

样品运行-

In [54]: list_a = [100, 5, 1, 2, 200, 3, 1, 300, 6, 6]

In [55]: ind_list = [0, 4, 7]

In [56]: intervaled_cumsum(list_a, ind_list)
Out[56]: array([100, 105, 106, 108, 200, 203, 204, 300, 306, 312])

答案 3 :(得分:2)

或者只是创建一个生成器:

def generate_running_sum(summands, index_list):
    current_sum = 0
    for i, summand in enumerate(summands):
        if i in set(index_list):
            current_sum = 0
        current_sum += summand
        yield current_sum

应用于您的数据:

list_a = [100, 5, 1, 2, 200, 3, 1, 300, 6, 6]
ind_list = [0, 4, 7]

res_list = list(generate_running_sum(summands=list_a, index_list=ind_list))
print(res_list)

答案 4 :(得分:1)

我通过zipnp.cumsum的组合来做到这一点。

我考虑了[0-4)[4-7)[7-(len(list)))的索引。

然后我找到列表中每个切片的累积总和,然后将其放在另一个列表中:

import numpy as np

list_a = [100, 5, 1, 2, 200, 3, 1, 300, 6, 6]
ind_list = [0, 4, 7]

def createcumsum(list_a, ind_list):
    # For adding the end of the list to the indexes if it doesn't exist
    if ind_list[-1] != len(list_a):
        ind_list.append(len(list_a))
    res_list=[]
    # Considers the indexes from 0-4, 4-7, 7-(endoflist)
    for x,y in zip(ind_list, ind_list[1:]):
        # Take cumulativesum on the above mentioned slices
        res_list.extend(np.cumsum(list_a[x:y]))
    return res_list
print(createcumsum(list_a, ind_list))

输出

[100, 105, 106, 108, 200, 203, 204, 300, 306, 312]

答案 5 :(得分:1)

最大itertools次滥用!

设置

from itertools import accumulate, chain, islice, tee

def pairwise(iterable):
    'pairwise recipe from itertools docs'
    it1, it2 = tee(iterable)
    next(it2)
    return zip(it1, it2)

list_a = [100, 5, 1, 2, 200, 3, 1, 300, 6, 6]
ind_list = [0, 4, 7]

解决方案

ind_list.append(None)
result = list(chain.from_iterable(accumulate(islice(list_a, start, stop))
              for start, stop in pairwise(ind_list)))

print(result)

输出

[100, 105, 106, 108, 200, 203, 204, 300, 306, 312]

在这里尽可能使用itertools工具的想法是避免创建不必要地占用内存的中间列表切片。

〜编辑~~

高效内存的Python 2.7解决方案

from itertools import chain, islice, izip, tee

def pairwise(iterable):
    'pairwise recipe from itertools docs'
    it1, it2 = tee(iterable)
    next(it2)
    return izip(it1, it2)

def my_cumsum(iterable):
    s = 0
    for x in iterable:
        s += x
        yield s

list_a = [100, 5, 1, 2, 200, 3, 1, 300, 6, 6]
ind_list = [0, 4, 7]

ind_list.append(None)
result = list(chain.from_iterable(my_cumsum(islice(list_a, start, stop))
              for start, stop in pairwise(ind_list)))

print(result)

答案 6 :(得分:1)

我必须手动扩展ind_list:

ind_list = [0, 4, 7] + [len(list_a)]

只需运行一个嵌套循环,并将嵌套范围设置为上述ind_list:

count, final = 0, []
for i in range(len(ind_list)-1):
    count = 0
    for i in range(ind_list[i],ind_list[i+1]):
        count += list_a[i]
        final.append(count)

答案 7 :(得分:1)

仅使用NumPy的答案稍微简单些:

import numpy as np
list_a = [100, 5, 1, 2, 200, 3, 1, 300, 6, 6]
ind_list = [2, 4, 7]
res_list = []

for i, n in enumerate(ind_list):
    if i == 0:
        n_prev=0
    else:
        n_prev = ind_list[i-1]
    for k in range(n-n_prev):
        res_list.append(np.sum(list_a[n_prev:n_prev+k+1]))
    if i == len(ind_list)-1:
        for k in range(len(list_a)-n):
            res_list.append(np.sum(list_a[n:n+k+1]))

print(res_list)

输出

[100, 105, 106, 108, 200, 203, 204, 300, 306, 312]