2

大きなリストがあり、その抜粋は次のようになります。

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]]
]

文字列の最初の数字は重要な数字であり、追加を分離したい数字です。つまり、各ステーション内の値を累積的に加算したい (そしてそれぞれの特異な累積加算を返したい) だけで、2 つの異なるステーションの値を加算することはありません。

私の目標は、このリストを反復処理し、ステーションの int 値を累積的に追加し、各追加を返し、リストで次のステーションが検出されたときに再び開始することです。

望ましい結果:

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'

ただし、この追加は累積的ではないため、使用できません。

4

2 に答える 2

2
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

例えば。

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

最初のグループです。ご覧のとおり、マトリックスの形式になっています。

zip(*nums)引数の解凍を使用して行列を転置します。呼び出す

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が呼び出されます。これは、次のようになります。

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

ご覧のとおり、各リストの最初の要素は必須ではないため、end()までisliceのインデックスから要素を取得するために使用されます。これは次のようになります。1None

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

これを転置する必要があります。

>>> zip(*(islice(accumulate(col), 1, None) for col in cols))
[(48, 1, -4, 11, 21), (51, 1, -9, 5, 21)]
于 2012-08-09T09:16:31.250 に答える
0

問題をより小さな部分に分割すると役立ちます。1)何らかの基準に基づいてリストを分割し、2)各サブリストの累積合計を取得する(各要素をベクトルと見なす)ことを理解しているようです。

例えば:

stationList = [
 ['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]]
]

なる:

{'1234-4321-1': [
    <5, 6, -4, 11, 22>, 
    <5, 6, -4, 11, 22> + <43, -5, 0, 0, -1>,
    <5, 6, -4, 11, 22> + <43, -5, 0, 0, -1> + <3, 0, -5, -6, 0>
 ], 
 '1567-3454-1': [
    <4, 6, 8, 3, 3>, 
    <4, 6, 8, 3, 3> + <1, 2, 1, -4, 5>
 ]
}

(ここで<...>は、仮想オブジェクトを表すために使用するVectorか、単にリストをベクトルとして扱います。)


解決

from itertools import *

1) いくつかの基準に基づいてリストを分割するには、 itertools.groupby: documentation hereを使用します。または、ジェネレーター関数を記述します。

getStation = lambda x: x[0].split('-')[0]
def groupby_station(inputList):
    return groupby(inputList, key=getStation)

2) 累積和は、生成関数として記述できます。を使用することもnumpy、自分で書くこともできます。

def listAdd(*lists):
    """
        listAdd([1,2,3], [10,20,30]) -> [11,22,33]
        listAdd([1,2,3], []) -> [1,2,3]
    """
    return [sum(xs) for xs in zip_longest(*lists, fillvalue=0)]

def cumSum(lists):
    """
        cumSum([1,2],[10,20],[100,200]) -> ([1,2],[11,22],[111,222])
    """
    total = []
    for list in lists:
        total = listAdd(total, list)
        yield total

2つを組み合わせるだけです:

{key:cumSum(*lists) for key,lists in groupby_station(inputList)}

私の累積和の定義はあなたのものとは少し異なることに注意してください。cumSum定義に一致するように関数を変更できます。

于 2012-08-09T08:49:59.440 に答える