[python-brasil] Dicionário - Agrupar, somar.

1,813 views
Skip to first unread message

Antonio Prado

unread,
Jun 1, 2010, 3:06:30 PM6/1/10
to Lista Python
Dado a seguinte lista de dicionários:

[
{'aliquota': 0, 'valor': 100},
{'aliquota': 0, 'valor': 200},
{'aliquota': 5, 'valor': 80},
{'aliquota': 5, 'valor': 50}
]


Qual a melhor forma para AGRUPAR pela chave alíquota,
para se chegar ao seguinte resultado:

[
{'aliquota': 0, 'valor': 300},
{'aliquota': 5, 'valor': 130}
]


Obrigado.


[]'s

Antonio

------------------------------------

,-----------------------------------------------------------.
| Antes de enviar um e-mail para o grupo leia: |
| http://www.pythonbrasil.com.br/moin.cgi/AntesDePerguntar |
| E se você é usuário do BOL lembre-se de cadastrar o |
| e-mail do grupo na lista branca do seu sistema anti-spam. |
`-----------------------------------------------------------´Links do Yahoo! Grupos

<*> Para visitar o site do seu grupo na web, acesse:
http://br.groups.yahoo.com/group/python-brasil/

<*> Para sair deste grupo, envie um e-mail para:
python-brasi...@yahoogrupos.com.br

<*> O uso que você faz do Yahoo! Grupos está sujeito aos:
http://br.yahoo.com/info/utos.html


Clodoaldo Neto

unread,
Jun 1, 2010, 3:37:14 PM6/1/10
to python...@yahoogrupos.com.br
Em 1 de junho de 2010 16:31, Douglas Soares de Andrade <dsan...@gmail.com>
escreveu:
>
>
>
> Antonio Prado escreveu:

>
> > Dado a seguinte lista de dicionários:
> >
> > [
> > {'aliquota': 0, 'valor': 100},
> > {'aliquota': 0, 'valor': 200},
> > {'aliquota': 5, 'valor': 80},
> > {'aliquota': 5, 'valor': 50}
> > ]
> >
> >
> > Qual a melhor forma para AGRUPAR pela chave alíquota,
> > para se chegar ao seguinte resultado:
> >
> > [
> > {'aliquota': 0, 'valor': 300},
> > {'aliquota': 5, 'valor': 130}
> > ]
>
> Olá Antonio,
>
> Acho que isso resolve:
>
> >>> valores
> [{'aliquota': 0, 'valor': 100}, {'aliquota': 0, 'valor': 200},

> {'aliquota': 5, 'valor': 80}, {'aliquota': 5, 'valor': 50}]
> >>> for i in valores:
> ... valor = dados.get(i['aliquota'],None)
> ... if valor:
> ... valor += i['valor']
> ... else:
> ... valor = i['valor']
> ... dados[i['aliquota']] = valor
> ...
> >>> valores
> [{'aliquota': 0, 'valor': 100}, {'aliquota': 0, 'valor': 200},

> {'aliquota': 5, 'valor': 80}, {'aliquota': 5, 'valor': 50}]
> >>> dados
> {0: 300, 5: 130}
> >>>

Eu acho que é até melhor do que o que ele pediu (uma lista de dicionários)
mas eu ia perguntar se a lista original não estava vindo de uma consulta
sql. Neste caso não seria melhor fazer o agrupamento na própria consulta
sql?

Saudações, Clodoaldo


[As partes desta mensagem que não continham texto foram removidas]

Antonio Prado

unread,
Jun 1, 2010, 4:15:09 PM6/1/10
to python...@yahoogrupos.com.br
Em Ter, 2010-06-01 às 16:31 -0300, Douglas Soares de Andrade escreveu:
>
> Antonio Prado escreveu:

> > Dado a seguinte lista de dicionários:
> >
> > [
> > {'aliquota': 0, 'valor': 100},
> > {'aliquota': 0, 'valor': 200},
> > {'aliquota': 5, 'valor': 80},
> > {'aliquota': 5, 'valor': 50}
> > ]
> >
> >
> > Qual a melhor forma para AGRUPAR pela chave alíquota,
> > para se chegar ao seguinte resultado:
> >
> > [
> > {'aliquota': 0, 'valor': 300},
> > {'aliquota': 5, 'valor': 130}
> > ]
>
> Olá Antonio,
>
> Acho que isso resolve:
>
> >>> valores
> [{'aliquota': 0, 'valor': 100}, {'aliquota': 0, 'valor': 200},
> {'aliquota': 5, 'valor': 80}, {'aliquota': 5, 'valor': 50}]
> >>> for i in valores:
> ... valor = dados.get(i['aliquota'],None)
> ... if valor:
> ... valor += i['valor']
> ... else:
> ... valor = i['valor']
> ... dados[i['aliquota']] = valor
> ...
> >>> valores
> [{'aliquota': 0, 'valor': 100}, {'aliquota': 0, 'valor': 200},
> {'aliquota': 5, 'valor': 80}, {'aliquota': 5, 'valor': 50}]
> >>> dados
> {0: 300, 5: 130}
> >>>


Após tantas instruções, posso dar como resolvido.

Muito obrigado a todos pela atenção.

Att.

Antonio.

Narcélio Filho

unread,
Jun 2, 2010, 4:00:38 PM6/2/10
to python...@yahoogrupos.com.br
> Dado a seguinte lista de dicionários:
> [{'aliquota': 0, 'valor': 100},
> {'aliquota': 0, 'valor': 200},
> {'aliquota': 5, 'valor': 80},
> {'aliquota': 5, 'valor': 50}]
>
> Qual a melhor forma para AGRUPAR pela chave alíquota,
> para se chegar ao seguinte resultado:
>
> [{'aliquota': 0, 'valor': 300},
> {'aliquota': 5, 'valor': 130}]


Python também tem "GROUP BY":


from itertools import groupby
from operator import itemgetter

tabela = [


{'aliquota': 0, 'valor': 100},
{'aliquota': 0, 'valor': 200},
{'aliquota': 5, 'valor': 80},
{'aliquota': 5, 'valor': 50}
]

agrupado = [
{
'aliquota': chave,
'valor': sum(linha['valor'] for linha in linhas)
} for chave, linhas in groupby(tabela, itemgetter('aliquota'))
]

--
[]s, Narcélio

Douglas Soares de Andrade

unread,
Jun 2, 2010, 4:27:31 PM6/2/10
to python...@yahoogrupos.com.br
Narcélio Filho escreveu:

>> Dado a seguinte lista de dicionários:
>> [{'aliquota': 0, 'valor': 100},
>> {'aliquota': 0, 'valor': 200},
>> {'aliquota': 5, 'valor': 80},
>> {'aliquota': 5, 'valor': 50}]
>>
>> Qual a melhor forma para AGRUPAR pela chave alíquota,
>> para se chegar ao seguinte resultado:
>>
>> [{'aliquota': 0, 'valor': 300},
>> {'aliquota': 5, 'valor': 130}]
>
>
> Python também tem "GROUP BY":
>
>
> from itertools import groupby
> from operator import itemgetter
>
> tabela = [
> {'aliquota': 0, 'valor': 100},
> {'aliquota': 0, 'valor': 200},
> {'aliquota': 5, 'valor': 80},
> {'aliquota': 5, 'valor': 50}
> ]
>
> agrupado = [
> {
> 'aliquota': chave,
> 'valor': sum(linha['valor'] for linha in linhas)
> } for chave, linhas in groupby(tabela, itemgetter('aliquota'))
> ]

Coisa linda !

Não conhecia esses poderes =)

Douglas Soares de Andrade

unread,
Jun 1, 2010, 3:31:44 PM6/1/10
to python...@yahoogrupos.com.br
Antonio Prado escreveu:

> Dado a seguinte lista de dicionários:
>
> [
> {'aliquota': 0, 'valor': 100},
> {'aliquota': 0, 'valor': 200},
> {'aliquota': 5, 'valor': 80},
> {'aliquota': 5, 'valor': 50}
> ]
>
>
> Qual a melhor forma para AGRUPAR pela chave alíquota,
> para se chegar ao seguinte resultado:
>
> [
> {'aliquota': 0, 'valor': 300},
> {'aliquota': 5, 'valor': 130}
> ]

Olá Antonio,

Acho que isso resolve:

>>> valores
[{'aliquota': 0, 'valor': 100}, {'aliquota': 0, 'valor': 200},

{'aliquota': 5, 'valor': 80}, {'aliquota': 5, 'valor': 50}]

>>> for i in valores:
... valor = dados.get(i['aliquota'],None)
... if valor:
... valor += i['valor']
... else:
... valor = i['valor']
... dados[i['aliquota']] = valor
...
>>> valores

[{'aliquota': 0, 'valor': 100}, {'aliquota': 0, 'valor': 200},

{'aliquota': 5, 'valor': 80}, {'aliquota': 5, 'valor': 50}]

>>> dados
{0: 300, 5: 130}
>>>

Vinícius Figueiredo

unread,
Jun 1, 2010, 3:34:21 PM6/1/10
to python...@yahoogrupos.com.br
2010/6/1 Antonio Prado <sup...@antonioprado.eti.br>

>
>
>
> Dado a seguinte lista de dicionários:
>
> [
> {'aliquota': 0, 'valor': 100},
> {'aliquota': 0, 'valor': 200},
> {'aliquota': 5, 'valor': 80},
> {'aliquota': 5, 'valor': 50}
> ]
>
> Qual a melhor forma para AGRUPAR pela chave alíquota,
> para se chegar ao seguinte resultado:
>
> [
> {'aliquota': 0, 'valor': 300},
> {'aliquota': 5, 'valor': 130}
> ]
>
> Obrigado.
>
> []'s
>
> Antonio
>

Segunda resposta pra 'python merge dict' no Google:

http://stackoverflow.com/questions/38987/how-can-i-merge-two-python-dictionaries-as-a-single-expression/44512#44512

>>> d1 = { 'aliquota': 0, 'valor': 100 }
>>> d2 = { 'aliquota': 0, 'valor': 200 }
>>> merge(d1, d2, lambda x,y: x+y)
{'aliquota': 0, 'valor': 300}

No link tem o código da função merge.

--
Vinícius Figueiredo

Junior Polegato - Linux

unread,
Jun 1, 2010, 3:51:59 PM6/1/10
to python...@yahoogrupos.com.br
Em 01-06-2010 16:06, Antonio Prado escreveu:
> Dado a seguinte lista de dicionários:
> [
> {'aliquota': 0, 'valor': 100},
> {'aliquota': 0, 'valor': 200},
> {'aliquota': 5, 'valor': 80},
> {'aliquota': 5, 'valor': 50}
> ]
> Qual a melhor forma para AGRUPAR pela chave alíquota,
> para se chegar ao seguinte resultado:
> [
> {'aliquota': 0, 'valor': 300},
> {'aliquota': 5, 'valor': 130}
> ]
>

Olá,

x = [{'aliquota': 0, 'valor': 100}, ...]
z = {}
for y in x:
....a = y['aliquota']
....z[a] = z[a] + y['valor'] if a in z else y['valor']
r = [{'aliquota': t, 'valor': z[t]} for t in z]

Veja que z já tem um resultado suficiente (z = {0: 300, 5:
130}), mas r é exatamente o que pediu (r = [{'aliquota': 0, 'valor':
300}, {'aliquota': 5, 'valor': 130}]).


[]'s
Junior Polegato

Filipe Fernandes

unread,
Jun 1, 2010, 3:34:59 PM6/1/10
to python...@yahoogrupos.com.br
Minha versão :

a = [{'aliquota': 0, 'valor': 100}, {'aliquota': 0, 'valor': 200},


{'aliquota': 5, 'valor': 80}, {'aliquota': 5, 'valor': 50}]

d = {}
res = []

for i in a:
if d.has_key(i.values()[0]):
d[i.values()[0]] += i.values()[1]
else:
d[i.values()[0]] = i.values()[1]

for i in d.items():
res.append({'aliquota':i[0], 'valor':i[1]})

print res # res = [{'aliquota': 0, 'valor': 300}, {'aliquota': 5, 'valor':
130}]

Em 1 de junho de 2010 16:31, Douglas Soares de Andrade
<dsan...@gmail.com>escreveu:

>
>

--
Atenciosamente

<><> Filipe Fernandes dos Santos <><>
Graduando em Ciência da Computação - UECE
Laboratório de Redes de Comunicação e Segurança da Informação (LARCES)


[As partes desta mensagem que não continham texto foram removidas]

------------------------------------

victorjabur

unread,
Jun 4, 2010, 7:06:35 PM6/4/10
to python...@yahoogrupos.com.br

Boa Noite a Todos,

Fiz uma implementação usando o reduce() do python,

alguém consegue melhorar este algoritmo para deixá-lo mais "elegante", ou pelo menos reduzir o número de linhas de código ?

def agruparSomar(lista):
lista.sort()
listaRetorno = []
def somar(dic1, dic2):
if(dic1['aliquota'] == dic2['aliquota']):
return {'aliquota' : dic1['aliquota'], 'valor' : dic1['valor'] + dic2['valor']}
else:
listaRetorno.append(dic1)
return dic2
ultimo = reduce(somar, lista)
listaRetorno.append(ultimo)
return listaRetorno

lista = [{'aliquota': 0, 'valor': 100},

{'aliquota': 5, 'valor': 80},

{'aliquota': 10, 'valor': 90},

{'aliquota': 0, 'valor': 200},

{'aliquota': 5, 'valor': 50},
{'aliquota': 10, 'valor': 90}]

print agruparSomar(lista)

[{'aliquota': 0, 'valor': 300}, {'aliquota': 5, 'valor': 130}, {'aliquota': 10, 'valor': 180}]

Abraços, ...
Victor Jabur


--- Em python...@yahoogrupos.com.br, Douglas Soares de Andrade <dsandrade@...> escreveu

Pinguim Azul

unread,
Jun 6, 2010, 12:26:05 PM6/6/10
to python...@yahoogrupos.com.br
Eu não acho que elegância tem necessariamente a ver com linhas de
código, mas dá pra fazer em uma linha só:

>>> print [{"aliquota":x, "valor":sum(y["valor"] for y in lista if y["aliquota"]==x)} for x in sorted(set(x["aliquota"] for x in lista))]


[{'aliquota': 0, 'valor': 300}, {'aliquota': 5, 'valor': 130},
{'aliquota': 10, 'valor': 180}]

2010/6/4 victorjabur <victo...@gmail.com>:

--
Ricardo Bittencourt
http://www.ricbit.com

Reply all
Reply to author
Forward
0 new messages