28

I have a python dictionary that looks something like this:

attributes = {
    'size': ['s','m','l'],
    'color': ['black', 'orange'],
}

I want to get a list of values. If I use values(), I get this:

>>> attributes.values()
[['black', 'orange'], ['s', 'm', 'l']]

However, I want the resulting list of lists to be sorted by the dictionary key in reverse order -- ie, size and then color, not color and then size. I want this:

[['s', 'm', 'l'], ['black', 'orange']]

I do not necesarilly know what the dictionary keys will be beforehand, but I do always know if I want them in alphabetical or reverse alphabetical order.

Is there some pythonic way to do this?

The only thing I can think of seems... not very python-like:

keys = sorted(attributes.keys(), reverse=True)
result = []
for key in keys:
    result.append(attributes[key])

It's hard to go from attributes.values() to all of that just to sort the list!

rigidfence
  • 295
  • 1
  • 3
  • 4
  • Dictionaries are non-ordered, so there is no simple way to specify the order in which dictionary keys are shown. You can order the display, but not the keys themselves in the dict. However, you could try using an Ordered Dict (included in Python 2.7+) to get around this. – Brian C Apr 14 '16 at 22:06
  • 2
    `sorted(attributes, reverse=True)`, you don't need .keys – Padraic Cunningham Apr 14 '16 at 22:21

2 Answers2

45

This code:

keys = sorted(attributes.keys(), reverse=True)
result = []
for key in keys:
    result.append(attributes[key])

Is basically the use case for which list comprehensions were invented:

result = [attributes[key] for key in sorted(attributes.keys(), reverse=True)]
kindall
  • 178,883
  • 35
  • 278
  • 309
  • 21
    You can save some lookups like so: `[value for key,value in sorted(attributes.items(), reverse=True)]` – Robᵩ Apr 14 '16 at 22:21
  • 1
    Or `result = [val for key, val in sorted(attributes.items(), reverse=True)]` to avoid a second round of lookups. __Edit__: Hah. Beaten to the punch. :-) – ShadowRanger Apr 14 '16 at 22:21
  • @Robᵩ Excellent point, but I was trying to make as few changes to the original code as possible so it was clear how it translated. – kindall Apr 14 '16 at 23:15
  • Great answer! So bizarre that this answer has so few votes :-\ – piRSquared Sep 05 '17 at 05:05
3

The easiest way is to use OrderedDict, which remembers the order in which the elements have been inserted:

import collections

result = collections.OrderedDict(sorted(attributes.items(), reverse=True))

>>> result.values()
[['s', 'm', 'l'], ['black', 'orange']]
lc123
  • 158
  • 9