累积加法,同时遍历列表 [英] Cumulative addition whilst looping over a list

查看:121
本文介绍了累积加法,同时遍历列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个很大的清单,摘录如下:

I have a large list, an excerpt of which looks like:

power = [
    ['1234-43211', [5, 6, -4, 11, 22]], 
    ['1234-783411', [43, -5, 0, 0, -1]], 
    ['1234-537611', [3, 0, -5, -6, 0]], 
    ['1567-345411', [4, 6, 8, 3, 3]], 
    ['1567-998711', [1, 2, 1, -4, 5]]
]

字符串中的第一个数字是重要的数字,我希望将其中的加号分开.也就是说,我只想在每个站点内累加值(并返回每个奇异的累加值),从不将两个不同的值相加.

The first number in the string is the important one, and the one in which I hope to separate my additions. i.e. I only want to add cumulatively the values within each station (and return each singular cumulative addition), never add the values from two different ones.

我的目标是遍历此列表,并累加一个站点的int值,返回每个加法,然后在列表中检测到下一个站点时重新开始.

My goal is to iterate over this list and add cumulatively the int values for a station, return each addition, then start again when the next station is detected in the list.

所需结果:

new = [
    [48, 1, -4, 11, -21], 
    [ 51, 1, -9, 5, -21], '### End of '1234' ### '
    [5,  8, 9, -1, 8], '### End of 1567 ###'
] or something similar to this

我尝试了以下操作:

for i in range(len(power)-1):
    front_num_1 = power[i][0].split('-')[0]
    front_num_2 = power[i+1][0].split('-')[0]
    station = '%s' % (front_num_1)
    j = power[i][1]
    k = power[i+1][1]

    if front_num_1 == front_num_2:
        print [k + j for k, j in zip(j, k)]

    elif front_num_1 != front_num_2:
        print  '#####################################

    else:
        print 'END'

但是这种加法不是累积的,因此没有用.

However this addition is not cumulative hence no use.

推荐答案

from itertools import groupby, islice

def accumulate(iterable): # in py 3 use itertools.accumulate
    ''' Simplified version of accumulate from python 3'''
    it = iter(iterable)
    total = next(it)
    yield total
    for element in it:
        total += element
        yield total

power = [
    ['1234-4321-1', [5, 6, -4, 11, 22]],
    ['1234-7834-1', [43, -5, 0, 0, -1]],
    ['1234-5376-1', [3, 0, -5, -6, 0]],
    ['1567-3454-1', [4, 6, 8, 3, 3]],
    ['1567-9987-1-', [1, 2, 1, -4, 5]]
]

groups = ((k, (nums for station, nums in g))
          for k, g in
          groupby(power, lambda x: x[0].partition('-')[0]))

new = [(station, zip(*(islice(accumulate(col), 1, None) for col in zip(*nums))))
        for station, nums in groups]

print new    

print dict(new) # or as a dictionary which is unordered

输出

[('1234', [(48, 1, -4, 11, 21), (51, 1, -9, 5, 21)]), ('1567', [(5, 8, 9, -1, 8)])]
{'1234': [(48, 1, -4, 11, 21), (51, 1, -9, 5, 21)], '1567': [(5, 8, 9, -1, 8)]}

工作原理:

首先,使用itertools.groupby根据电台对列表进行分组.

First the lists are grouped based on the station using itertools.groupby.

例如.

nums = [[5, 6, -4, 11, 22], 
        [43, -5, 0, 0, -1], 
        [3, 0, -5, -6, 0]]

是第一组.如您所见,它是矩阵形式.

is the first group. As you can see it is in the form of a matrix.

zip(*nums) 使用参数解包来转置矩阵.它调用

zip(*nums) transposes a matrix using argument unpacking. It calls

zip([5, 6, -4, 11, 22], [43, -5, 0, 0, -1], [3, 0, -5, -6, 0])

这将创建列表:

cols = [(5, 43, 3), (6, -5, 0), (-4, 0, -5), (11, 0, -6), (22, -1, 0)]

然后在每一列上调用accumulate,如下所示:

then accumulate is called on each column, here's what that would look like:

>>> [list(accumulate(col)) for col in cols]
[[5, 48, 51], [6, 1, 1], [-4, -4, -9], [11, 11, 5], [22, 21, 21]]

如您所见,这里不需要每个列表中的第一个元素,因此islice用于从索引1中获取元素,直到end(None).看起来像这样:

As you can see the first element in each list here is not required so islice is used to take the elements from index 1 until then end(None). Here's what that looks like:

>>> [list(islice(accumulate(col), 1, None)) for col in cols]
[[48, 51], [1, 1], [-4, -9], [11, 5], [21, 21]]

现在我们只需要将其转置回去.

Now we just need to transpose this back.

>>> zip(*(islice(accumulate(col), 1, None) for col in cols))
[(48, 1, -4, 11, 21), (51, 1, -9, 5, 21)]

这篇关于累积加法,同时遍历列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆