Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

list comprehension (searching for onliners)

10 views
Skip to first unread message

Gerardo Herzig

unread,
Oct 20, 2006, 8:27:10 AM10/20/06
to pytho...@python.org
Hi all: I have this list thing as a result of a db.query: (short version)
result = [{'service_id' : 1, 'value': 10},
{'service_id': 2, 'value': 5},
{'service_id': 1, 'value': 15},
{'service_id': 2, 'value': 15},
]

and so on...what i need to do is some list comprehension that returns me
something like

result = [
{
'service_id' : 1, 'values': [ {'value': 10},
{'value': 15}]
},
{
'service_id' : 2, 'values': [ {'value': 5}, {'value': 15}]
}

My problem now is i cant avoid have "repeteated" entries, lets say, in
this particular case, 2 entries for "service_id = 1", and other 2 for
"service_id =2".
Ill keeping blew off my hair and drinking more cofee while searching for
this damn onliner im looking for.

Thanks dudes.
Gerardo

Max Erickson

unread,
Oct 20, 2006, 8:58:01 AM10/20/06
to pytho...@python.org
Gerardo Herzig <ghe...@fmed.uba.ar> wrote:

Is three lines ok?

>>> output=dict()
>>> for record in result:
output.setdefault(record['service_id'], list()).append(record
['value'])


>>> output
{1: [10, 15], 2: [5, 15]}
>>>

Creating the more verbose output that you specified should be
pretty straighforward from there.

max

Tim Chase

unread,
Oct 20, 2006, 9:04:16 AM10/20/06
to Gerardo Herzig, pytho...@python.org
> result = [{'service_id' : 1, 'value': 10},
> {'service_id': 2, 'value': 5},
> {'service_id': 1, 'value': 15},
> {'service_id': 2, 'value': 15},
> ]
>
> and so on...what i need to do is some list comprehension that returns me
> something like
>
> result = [
> {
> 'service_id' : 1, 'values': [ {'value': 10},
> {'value': 15}]
> },
> {
> 'service_id' : 2, 'values': [ {'value': 5}, {'value': 15}]
> }
>
>
> My problem now is i cant avoid have "repeteated" entries, lets say, in
> this particular case, 2 entries for "service_id = 1", and other 2 for
> "service_id =2".

Okay...while I'm not sure the opacity of a one-liner is actually
productive, it *can* be done. Whether it should, I leave that to
your discernment. :)

>>> [{'service_id': i, 'values':[{'value':d2['value']} for d2 in
result if d2['service_id'] == i ]} for i in set(d['service_id']
for d in result)]

[{'service_id': 1, 'values': [{'value': 10}, {'value': 15}]},
{'service_id': 2, 'values': [{'value': 5}, {'value': 15}]}]


There's no claiming it's efficient, as it looks like there may be
some O(N^2) logic going on under the hood (or possibly O(N*M)
where N is the size of the result-set and M is the count of
unique service_id values), as it's iterating over the result-set
in two dimensions...once to create the set of top-level indices,
and once for each result.

If you didn't have to have all those dictionaries around, it
might come out more cleanly to just have some result-set that
came out to be

{1: [10,15], 2: [5,15]}

Just a few thoughts...

-tkc

Jon Clements

unread,
Oct 20, 2006, 9:14:13 AM10/20/06
to

Gerardo Herzig wrote:

If you import itertools and have your DB query return in order of
service_id (or sort the list after retrieving result), then...


[ [dict(service_id=key),[dict(value=n['value']) for n in value]] for
key,value in itertools.groupby(result,lambda x: x['service_id']) ]

... is more or less what you want.

Jon.

Gerardo Herzig

unread,
Oct 20, 2006, 10:47:03 AM10/20/06
to Tim Chase, pytho...@python.org
You are the man, you are the man!! Yes, i need those dicts in order to
assign them to a nested <TMPL_LOOP> for the htmltmpl templating engine.
Thats why i cant use the solution provided by Max, and thanks to Jon too!!
Thanks a lot dudes, i hope someday ill turn myself into some of you guys
who can actually answer questions ;)

Gerardo

>> result = [{'service_id' : 1, 'value': 10},
>> {'service_id': 2, 'value': 5},
>> {'service_id': 1, 'value': 15},
>> {'service_id': 2, 'value': 15},
>> ]
>>
>> and so on...what i need to do is some list comprehension that returns
>> me something like
>>
>> result = [
>> {
>> 'service_id' : 1, 'values': [ {'value': 10},
>> {'value': 15}]
>> },
>> {
>> 'service_id' : 2, 'values': [ {'value': 5}, {'value': 15}]
>> }
>>
>> My problem now is i cant avoid have "repeteated" entries, lets say,
>> in this particular case, 2 entries for "service_id = 1", and other 2
>> for "service_id =2".
>
>

Paul Rubin

unread,
Oct 20, 2006, 10:46:30 AM10/20/06
to
Gerardo Herzig <ghe...@fmed.uba.ar> writes:
> You are the man, you are the man!! Yes, i need those dicts in order to
> assign them to a nested <TMPL_LOOP> for the htmltmpl templating
> engine. Thats why i cant use the solution provided by Max, and thanks
> to Jon too!!

I'm confused, can't you write a multi-line function and pass that?

Fredrik Lundh

unread,
Oct 20, 2006, 10:53:43 AM10/20/06
to pytho...@python.org
Gerardo Herzig wrote:

> Thanks a lot dudes, i hope someday ill turn myself into some of you guys
> who can actually answer questions ;)

if you want to become a good Python programmer, you really need to get
over that "I need a oneliner" idea.

</F>

Roberto Bonvallet

unread,
Oct 20, 2006, 10:50:38 AM10/20/06
to
Gerardo Herzig wrote:
[...]

> and so on...what i need to do is some list comprehension that returns me
> something like
[...]

You don't _need_ a list comprehension, you just _want_ one :)

[...]


> Ill keeping blew off my hair and drinking more cofee while searching for
> this damn onliner im looking for.

I know, trying to put complex logic in one line makes you do all that.

Go for the multiliner!
--
Roberto Bonvallet

Carsten Haese

unread,
Oct 20, 2006, 11:33:36 AM10/20/06
to pytho...@python.org
On Fri, 2006-10-20 at 10:53, Fredrik Lundh wrote:
> if you want to become a good Python programmer, you really need to get
> over that "I need a oneliner" idea.

+1 QOTW

-Carsten


0 new messages