Sorting dictionary by 'sub' value

  • Thread starter Rory Campbell-Lange
  • Start date
R

Rory Campbell-Lange

I have a dictionary of images. I wish to sort the dictionary 'v' by a
dictionary value using python 2.3. The dictionary value is the date
attribute as shown here:

v[imagename][9]['date']

This attribute is an extracted EXIF value from the following set:

data element [9] of v[imagename]:

{'now' : datetime.date(2005, 3, 7),
'y' : (0x011B) Ratio=72 @ 182,
'ctime' : datetime.date(2005, 3, 7),
'width' : (0xA002) Long=1024 @ 434,
'length' : (0xA003) Long=768 @ 446,
'date' : (0x9004) ASCII=2004:12:07 00:18:20 @ 514,
'x' : (0x011A) Ratio=72 @ 174,
'model' : (0x0110) ASCII=PENTAX Optio 330 @ 156,
'size' : 367415L,
'orientation' : (0x0112) Short=1 @ 42}

Thanks,
Rory
 
D

Diez B. Roggisch

I have a dictionary of images. I wish to sort the dictionary 'v' by a
dictionary value using python 2.3. The dictionary value is the date
attribute as shown here:

v[imagename][9]['date']

This attribute is an extracted EXIF value from the following set:

data element [9] of v[imagename]:

{'now' : datetime.date(2005, 3, 7),
'y' : (0x011B) Ratio=72 @ 182,
'ctime' : datetime.date(2005, 3, 7),
'width' : (0xA002) Long=1024 @ 434,
'length' : (0xA003) Long=768 @ 446,
'date' : (0x9004) ASCII=2004:12:07 00:18:20 @ 514,
'x' : (0x011A) Ratio=72 @ 174,
'model' : (0x0110) ASCII=PENTAX Optio 330 @ 156,
'size' : 367415L,
'orientation' : (0x0112) Short=1 @ 42}


You can't sort dicts - they don't impose an order on either key or value.
There are ordered dict implementations out there, but AFAIK the only keep
the keys sorted, or maybe the (key,values) in the insertion order.

But maybe this helps you:

l = v.items()
l.sort(lambda a, b: cmp(a[9]['date'], b[9]['date'])
 
S

Scott David Daniels

Diez said:
I have a dictionary of images. I wish to sort the dictionary 'v' by a
dictionary value using python 2.3. The dictionary value is the date
attribute as shown here:

v[imagename][9]['date']
...

You can't sort dicts - they don't impose an order on either key or value.
There are ordered dict implementations out there, but AFAIK the only keep
the keys sorted, or maybe the (key,values) in the insertion order.

But maybe this helps you:

l = v.items()
l.sort(lambda a, b: cmp(a[9]['date'], b[9]['date'])

In 2.4, this is simple:

ordered_keys = sorted(v, key=lambda name: v[name][9]['date'])

In 2.3, or earlier, use "decorate-sort-undecorate":

decorated = [(value[9]['date'], key)
for key, value in v.iteritems()]
decorated.sort()
result = [key for key, date in decorated]

--Scott David Daniels
(e-mail address removed)
 
R

Rory Campbell-Lange

Thank you all very much for your help.

I did the following and it works:

imgs=v.keys()
imgs.sort(lambda a,b: cmp(
time.strptime(str(v[a][9]['date']), '%Y:%m:%d %H:%M:%S'),
time.strptime(str(v[9]['date']), '%Y:%m:%d %H:%M:%S'))
)
for i in imgs:
...

Regards,
Rory

l = v.items()
l.sort(lambda a, b: cmp(a[9]['date'], b[9]['date'])
You can't sort dicts - they don't impose an order on either key or value.
There are ordered dict implementations out there, but AFAIK the only keep
the keys sorted, or maybe the (key,values) in the insertion order.

But maybe this helps you:

l = v.items()
l.sort(lambda a, b: cmp(a[9]['date'], b[9]['date'])

In 2.4, this is simple:

ordered_keys = sorted(v, key=lambda name: v[name][9]['date'])

In 2.3, or earlier, use "decorate-sort-undecorate":

decorated = [(value[9]['date'], key)
for key, value in v.iteritems()]
decorated.sort()
result = [key for key, date in decorated]
temp_list = [ (x[1][1], x[0]) for x in d.items() ] ....
temp_list.sort()
for (tmp, key) in temp_list:
 
S

Steven Bethard

Rory said:
Thank you all very much for your help.

I did the following and it works:

imgs=v.keys()
imgs.sort(lambda a,b: cmp(
time.strptime(str(v[a][9]['date']), '%Y:%m:%d %H:%M:%S'),
time.strptime(str(v[9]['date']), '%Y:%m:%d %H:%M:%S'))
)
for i in imgs:
...


Cool. If you ever find that this is a speed problem, it's worth
pointing out that the decorate-sort-undecorate pattern is usually
slightly faster:

------------------------------ test.py ------------------------------
import datetime
import time

# returns data in a similar format to yours
def get_data(n):
today = datetime.datetime(2005, 3, 8)
deltas = [datetime.timedelta(seconds=1e6*i)
for i in xrange(-n, n)]
times = [(today + delta).strftime('%Y:%m:%d %H:%M:%S')
for delta in deltas]
return dict([(i, {9:{'date':time}})
for i, time in enumerate(times)])

def sortcmp(data):
imgs = data.keys()
imgs.sort(lambda a,b: cmp(
time.strptime(str(data[a][9]['date']),
'%Y:%m:%d %H:%M:%S'),
time.strptime(str(data[9]['date']),
'%Y:%m:%d %H:%M:%S'))
)
return imgs

def sortdsu(data):
decorated = [(time.strptime(str(data[key][9]['date']),
'%Y:%m:%d %H:%M:%S'), key)
for key in data]
decorated.sort()
return [key for date, key in decorated]

# Requires 2.4
def sortkey(data):
def value(key):
return time.strptime(str(data[key][9]['date']),
'%Y:%m:%d %H:%M:%S')
return sorted(data, key=value)
---------------------------------------------------------------------

And the timing results:

[D:\Steve]$ python -m timeit -s "import test; d = test.get_data(1000)"
"test.sortcmp(d)"
10 loops, best of 3: 274 msec per loop

[D:\Steve]$ python -m timeit -s "import test; d = test.get_data(1000)"
"test.sortdsu(d)"
10 loops, best of 3: 131 msec per loop

# Requires 2.4

[D:\Steve]$ python -m timeit -s "import test; d = test.get_data(1000)"
"test.sortkey(d)"
10 loops, best of 3: 131 msec per loop

HTH,

STeVe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,128
Latest member
ElwoodPhil
Top