2

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
4
  • 2
    dictionaries are unsorted Commented Mar 28, 2017 at 13:27
  • Dictionaries can be sorted when iteritems is called though. Commented Mar 28, 2017 at 13:29
  • @JonathanConnell: That doesn't mean you can get your desired output. Commented Mar 28, 2017 at 13:30
  • So why are you using data.keys()[2]? The key order is arbitrary, whatever key at index 2 is should not inform your sort. And all your items are sorted on the basis of that one key. Did you mean x[0][2] perhaps (so the first element of the (key, value) pair or key, then the third element in that tuple). Commented Mar 28, 2017 at 13:32

2 Answers 2

3

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
Sign up to request clarification or add additional context in comments.

12 Comments

The actual problem is the sort key, which you fixed but didn't explain.
@MartijnPieters: that's why they invented something as edit. To first give an answer the op can test, and then explain. So that less time is wasted if the answer does not meet the expectations :). I notice you actually nearly always do the same :)
The revisions of the post show that the key=lambda x: data.keys()[2] version was there in the first 5 minutes.
There is an unusual caveat though: I am using this to say 'for key, value in sorted_dict: x = key[2], y = key[3] etc. For this, it reverts back to being unsorted even though if I print sorted_dict it is alphabetically sorted.
@JonathanConnell: but as specified in the answer: a dictionary is unoredered. You have to make zzz an OrderedDict as well ito maintain order at that level.
|
3

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.

1 Comment

I think you have to use x[0][2] since the iteritems() emit (key,value) tuples.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.