[Tutor] sorting objects on two attributes
Kent Johnson
kent37 at tds.net
Mon Mar 3 17:00:20 CET 2008
Eric Abrahamsen wrote:
> I have a list of objects, each of which has two attributes, object_id
> and submit_date. What I want is to sort them by content_type, then by
> submit_date within content_type, and then sort each content_type block
> according to which block has the newest object by submit_date. (This
> sequence of sorting might not be optimal, I'm not sure). I'm actually
> creating a list of recent comments on blog entries for a python-based
> web framework, and want to arrange the comments according to blog
> entry (content_type), by submit_date within that entry, with the
> entries with the newest comments showing up on top.
This description doesn't match your code. There is no content_type in
the code.
I think what you want to do is group the comments by object_id, sort
within each object_id group by submit_date, then sort the groups by most
recent submit date.
> I don't believe a single cmp function fed to list.sort() can do this,
> because you can't know how two objects should be compared until you
> know all the values for all the objects. I'd be happy to be proven
> wrong here.
Django's SortedDict might help. Perhaps this:
from operator import attrgetter
from django.utils.datastructures import SortedDict
sd = SortedDict()
for com in sorted(queryset, key=attrgetter.submit_date, reverse=True):
sd.setdefault(com.object.id, []).append(com)
Now sd.keys() is a list of object_ids in descending order by most recent
comment, and sd[object_id] is a list of comments for object_id, also in
descending order by submit_date. If you want the comments in increasing
date order (which I think your code below does) then you have to reverse
the lists of comments, e.g.
for l in sd.values():
l.reverse()
or just reverse at the point of use with the reversed() iterator.
> def make_com_list(queryset):
> ids = set([com.object_id for com in queryset])
> xlist = [[com for com in queryset if com.object_id == i] for i in
> ids]
> for ls in xlist:
> ls.sort(key=lambda x: x.submit_date)
> xlist.sort(key=lambda x: max([com.submit_date for com in x]),
> reverse=True)
No need for max() since the list is sorted; use
key=lambda x: x[-1].submit_date
Kent
More information about the Tutor
mailing list