[Tutor] Question about sorting a list within a dictionary within a list
Peter Otten
__peter__ at web.de
Mon Aug 1 22:03:18 CEST 2011
ian douglas wrote:
> I'm using the Bono library for talking to EC2, and I'm getting a list of
> EC2 instances back in a list called "reservations". Each element in the
> list is a dictionary of information. One of those dictionary elements is
> a list called 'instances', and I only ever care about the first entry.
> That instances[0] value is a dictionary, which holds a key I want to use
> to sort the base "reservations" list.
>
> I found this helpful bit for sorting a list of dictionaries by a key
> within the dictionaries:
> http://stackoverflow.com/questions/72899/in-python-how-do-i-sort-a-list-
of-dictionaries-by-values-of-the-dictionary
>
> ... this works great if you just have a list of dictionaries. I'm not
> sure how to go deeper within that to sort my data without iterating
> through the entire 'reservations' list and building an entirely new
> list. Maybe it would be easier, but I'm just curious if it's possible
> without messing with my main 'reservations' list.
>
>
> My current code looks like this: (it's a views.py file)
>
> from django.http import HttpResponse
> import boto.ec2
> from operator import itemgetter
>
> def index(request):
> conn = boto.connect_ec2()
> reservations = conn.get_all_instances()
>
> # this is where I'm trying to sort everything
> res_sorted = sorted(reservations, key=itemgetter('launch_time'))
>
> output = '<table>'
> output += '<tr>'
> output += '<th>State</th>'
> output += '<th>Launched</th>'
> output += '<th>Public Hostname</th>'
> output += '<th>Public IP</th>'
> output += '<th>Private Hostname</th>'
> output += '<th>Private IP</th>'
> output += '</tr>'
> for reservation in res_sorted:
> instance = reservation.instances[0]
> output += '<tr>'
> output += '<td>' + instance.state + '</td>'
> output += '<td>' + instance.launch_time + '</td>'
> output += '<td>' + instance.public_dns_name + '</td>'
> output += '<td>' + instance.ip_address + '</td>'
> output += '<td>' + instance.private_dns_name + '</td>'
> output += '<td>' + instance.private_ip_address + '</td>'
>
>
> Ideally, I'd like to make each table column 'sortable' so the user can
> click on state/launched/etc (I may add more columns in the future), but
> I'm not sure how to search deeper within the 'reservations' list for the
> sorted() call to get at the 'launch_time' element within the instaces[0]
> dictionary.
>
> Also, I'm sure there are much better ways to do the display logic, but
> I'll tackle that another time.
I cannot help you with the django or boto part. As to sorting lists: to do
it inplace invoke the sort() method:
reservations.sort(key=mykey)
You can think of itemgetter("launch_time") as a function that creates the
the following function on the fly:
def mykey(item):
return item["launch_time"]
Judging from the code you provide you need
def mykey(item):
return item.instances[0].launch_time
instead. If you want to be flexible about the actual attribute you can
change that to
attrname = ...
def mykey(item):
return getattr(item.instances[0], attrname)
Djange probably offers a way to provide the desired attribute name via the
request object. Your index() function would then become
LEGAL_SORTKEYS = set(["launch_time", "ip_address"])
def index(request):
conn = boto.connect_ec2()
reservations = conn.get_all_instances()
attrname = ... # your code
if attrname in LEGAL_SORTKEYS:
def mykey(item):
return getattr(item.instances[0], attrname)
reservations.sort(key=mykey)
else:
... # provide an error message or just don't sort
output = '<table>'
output += '<tr>'
...
More information about the Tutor
mailing list