[python] Suma podle klice slovniku v seznamu

Petr Přikryl prikryl na atlas.cz
Úterý Duben 16 15:59:35 CEST 2013


Ještě to řešení s sqlite. (Skoro s tím nedělám, tak tam možná půjde
udělat něco lépe -- někdo to opravte nebo ukažte, jak na to.)

import sqlite3

lst1 = [{'a':4,'b':3,'c':9},{'a':4,'b':5,'c':9},{'a':1,'b':3,'c':7},{'a':3,'b':2,'c':6}]
print('puvodni seznam slovniku:', lst1)

# Tabulku si uděláme jen v paměti.
con = sqlite3.connect(":memory:")
c = con.cursor()
c.execute('create table abc (A, B, C)')

# Naplníme ji hodnotami ze slovníků.
for x in lst1:
    c.execute('insert into abc values (:a, :b, :c)', x)

# Zobrazíme, co jsme tam nastrkali.
c.execute('select * from abc')
print('select * ...:', c.fetchall())

# A tohle je ten chtěný dotaz.
c.execute('''select A, sum(B), C
             from abc
             group by a, c''')
print('select A, sum(B), C ...:', c.fetchall())

con.close()

Slovníky tu z výsledku dělat nebudu :)

P.

______________________________________________________________
> Od: "Petr Přikryl" <prikryl na atlas.cz>
> Komu: Konference PyCZ <python na py.cz>
> Datum: 16.04.2013 15:35
> Předmět: Re: [python] Suma podle klice slovniku v seznamu
>
>Je to tím, že tam nedoplňuješ aktuální hodnotu toho c. Musí se zapamatovat
>pro každé a. Může se zapamatovat třeba tak, že se do pomocného slovníku bude 
>ukládat spolu se sumovanou hodnotou. Třeba takto:
>
>lst1 = [{'a':4,'b':3,'c':9},{'a':4,'b':5,'c':9},{'a':1,'b':3,'c':7},{'a':3,'b':2,'c':6}]
>print('puvodni seznam slovniku:', lst1)
>
>lst2 = [(x['a'], x['b'], x['c']) for x in lst1]
>print('seznam trojic hodnot:', lst2)
>
>d = {}
>for a, b, c in lst2:
>    sum_lst = d.setdefault(a, [0, c]) # seznam, kde k prvnímu prvku se přičítá...
>    sum_lst[0] += b                   # ... hodnota b
>print('slovnik sum:', d)
>
>lst3 = [{'a': a, 'b': b, 'c': c} for a, (b, c) in d.items()]
>print('vysledny seznam:', lst3)
>
>(Ono se to formátování zase zprasí, takže ty dva řádky se sum_lst jsou odsazené
>pod for.)
>
>Petr
>______________________________________________________________
>> Od: "Jaroslav Lukesh" <lukesh na seznam.cz>
>> Komu: Konference PyCZ <python na py.cz>
>> Datum: 16.04.2013 15:06
>> Předmět: Re: [python] Suma podle klice slovniku v seznamu
>>
>>Ahoj a díky za rozšíření obzorů.
>>
>>Jsou to data ne zrovna jednoduše vycucaná z databáze, o nějaké dočasné 
>>tabulcev sqlu  jsem uvažoval protože je nad tímto selektivně sečteným 
>>výsledkem víc operací, ale připadalo mi to jako ne příliš čisté řešení. 
>>Otrocky s pomocnýma proměnnýma to taky jde, ale chtěl jsem vědět, jeslti na 
>>to není nějaký fígl, protože mi připadalo logické, aby pro práci nad poli a 
>>slovníky bylo aspoň trochu něco jako je v sql.
>>
>>Ale mám s tím trošku problém, izoloval jsem problém pro tento příklad až 
>>příliš moc, protože se mi nedaří jej rozšířit o 'c', tedy pro tento vstup 
>>(podotýkám jen, že hodnota 'c' je stejná pro všechny 'a'):
>>
>>[{'a':4,'b':3,'c':9},{'a':4,'b':5,'c':9},{'a':1,'b':3,'c':7},{'a':3,'b':2,'c':6}]
>>
>>chtěl tento výstup:
>>
>>[{'a': 4, 'b': 8, 'c':9}, {'a': 1, 'b': 3, 'c':7}, {'a': 3, 'b': 2, 'c':6}]
>>
>>Tady je přehled co jsem zkoušel, tyhle dvě jdou, ale vrací špatné 'c'
>>
>>=========
>>
>>lst1 = 
>>[{'a':4,'b':3,'c':9},{'a':4,'b':5,'c':9},{'a':1,'b':3,'c':7},{'a':3,'b':2,'c':6}]
>>lst2 = [(x['a'], x['b'], x['c']) for x in lst1]
>>d = {}
>>for a, b,c in lst2:
>>    d[a] = d.get(a, 0) + b  # dosavadní součet nebo nula plus nová hodnota
>>lst3 = [{'a': a, 'b': b, 'c': c} for a, b in d.items()]
>>print('vysledny seznam:', lst3)
>>
>>======
>>
>>from itertools import groupby
>>def summarize(data):
>>    get_b = lambda x: x['b']
>>    get_a = lambda x: x['a']
>>    get_c = lambda x: x['c']
>>    return (
>>        {'a': val, 'b': sum(map(get_b, group)),'c':val}
>>        for (val, group)
>>        in groupby(data, key=get_a)
>>    )
>>data= 
>>[{'a':4,'b':3,'c':9},{'a':4,'b':5,'c':9},{'a':1,'b':3,'c':7},{'a':3,'b':2,'c':6}]
>>print list(summarize(data))
>>
>>=======
>>
>>A toto už háže chybu
>>
>>from itertools import groupby
>>from operator import itemgetter
>>def summarize(data):
>>    get_a = itemgetter('a')
>>    get_b = itemgetter('b')
>>    get_c = itemgetter('c')
>>    return (
>>        {'a': val, 'b': sum(map(get_b, group)),'c':valc}
>>        for (val, group,valc)
>>        in groupby(data, key=get_a)
>>    )
>>data= 
>>[{'a':4,'b':3,'c':9},{'a':4,'b':5,'c':9},{'a':1,'b':3,'c':7},{'a':3,'b':2,'c':6}]
>>print list(summarize(data))
>>
>>
>>_______________________________________________
>>Python mailing list
>>Python na py.cz
>>http://www.py.cz/mailman/listinfo/python
>>
>_______________________________________________
>Python mailing list
>Python na py.cz
>http://www.py.cz/mailman/listinfo/python
>


Další informace o konferenci Python