Sadie LaBounty
Sadie LaBounty

Reputation: 379

Python - Sorting a Tuple-Keyed Dictionary by Tuple Value

I have a dictionary constituted of tuple keys and integer counts and I want to sort it by the third value of the tuple (key[2]) as so

data = {(a, b, c, d): 1, (b, c, b, a): 4, (a, f, l, s): 3, (c, d, j, a): 7}
print sorted(data.iteritems(), key = lambda x: data.keys()[2])

with this desired output

>>> {(b, c, b, a): 4, (a, b, c, d): 1, (c, d, j, a): 7, (a, f, l, s): 3}

but my current code seems to do nothing. How should this be done?

Edit: The appropriate code is

sorted(data.iteritems(), key = lambda x: x[0][2])

but in the context

from collections import Ordered Dict 
data = {('a', 'b', 'c', 'd'): 1, ('b', 'c', 'b', 'a'): 4, ('a', 'f', 'l', 's'): 3, ('c', 'd', 'j', 'a'): 7}
xxx = []
yyy = []
zzz = OrderedDict()
for key, value in sorted(data.iteritems(), key = lambda x: x[0][2]):
    x = key[2]
    y = key[3]
    xxx.append(x)
    yyy.append(y)
    zzz[x + y] = 1
print xxx
print yyy
print zzz

zzz is unordered. I know that this is because dictionaries are by default unordered and that I need to use OrderedDict to sort it but I don't know where to use it. If I use it as the checked answer suggests I get a 'tuple index out of range' error.

Solution:

from collections import OrderedDict 
data = {('a', 'b', 'c', 'd'): 1, ('b', 'c', 'b', 'a'): 4, ('a', 'f', 'l', 's'): 3, ('c', 'd', 'j', 'a'): 7}
xxx = []
yyy = []
zzz = OrderedDict()
for key, value in sorted(data.iteritems(), key = lambda x: x[0][2]):
    x = key[2]
    y = key[3]
    xxx.append(x)
    yyy.append(y)
    zzz[x + y] = 1
print xxx
print yyy
print zzz

Upvotes: 2

Views: 1521

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476544

Dictionaries are unordered in Python. You can however use an OrderedDict.

You then have to sort like:

from collections import OrderedDict

result = OrderedDict(sorted(data.iteritems(),key=lambda x:x[0][2]))

You need to use key=lambda x:x[0][2] because the elements are tuples (key,val) and so to obtain the key, you use x[0].

This gives:

>>> data = {('a', 'b', 'c', 'd'): 1, ('b', 'c', 'b', 'a'): 4, ('a', 'f', 'l', 's'): 3, ('c', 'd', 'j', 'a'): 7}
>>> from collections import OrderedDict
>>> result = OrderedDict(sorted(data.iteritems(),key=lambda x:x[0][2]))
>>> result
OrderedDict([(('b', 'c', 'b', 'a'), 4), (('a', 'b', 'c', 'd'), 1), (('c', 'd', 'j', 'a'), 7), (('a', 'f', 'l', 's'), 3)])

EDIT:

In order to make zzz ordered as well, you can update your code to:

data = {('a', 'b', 'c', 'd'): 1, ('b', 'c', 'b', 'a'): 4, ('a', 'f', 'l', 's'): 3, ('c', 'd', 'j', 'a'): 7}
xxx = []
yyy = []
zzz = OrderedDict()
for key, value in sorted(data.iteritems(), key = lambda x: x[0][2]):
    x = key[2]
    y = key[3]
    xxx.append(x)
    yyy.append(y)
    zzz[x + y] = 1
print xxx
print yyy
print zzz

Upvotes: 3

Daniel Roseman
Daniel Roseman

Reputation: 599490

Your key function is completely broken. It's passed the current value as x, but you ignore that and instead always get the second item from the list of keys.

Use key=lambda x: x[0][2] instead.

Upvotes: 3

Related Questions