Bryan Veloso
Bryan Veloso

Reputation: 1595

Sorting dictionary keys by values in a list?

I have a dictionary and a list. The values of the keys match those of the list, I'm just trying to find out how to sort the values in the dictionary by the values in the list.

>>> l = [1, 2, 37, 32, 4, 3]
>>> d = {
    32: 'Megumi', 
    1: 'Ai',
    2: 'Risa',
    3: 'Eri', 
    4: 'Sayumi', 
    37: 'Mai'
}

I've tried using something along the lines of...

>>> sorted(dict.keys(), key=list.index)

... but obviously that only returns the keys in the desired order.

(Should have realized at 3AM that list and dict were horrible names, I changed them to l and d accordingly.)

Upvotes: 6

Views: 5604

Answers (5)

tux21b
tux21b

Reputation: 94639

You shouldn't call you variables dict and list, because then, you cant use the build-in methods any more. I have renamed them in this example.

>>> l = [1, 2, 37, 32, 4]
>>> d = dict = {
...     32: 'Megumi', 
...     1: 'Ai',
...     2: 'Risa',
...     3: 'Eri', 
...     4: 'Sayumi', 
...     37: 'Mai'
... }

Note that prior to Python 3.7 you could not sort dictionaries in Python (they were hash tables sorted by the hash functions of the keys). Alternative dictionary implementations existed to work around this (OrderedDict).

But you can create a new list containing the (key, value)-tuples from any dictionary, which is sorted by the first list:

>>> s = list((i, d.get(i)) for i in L)
>>> print s
[(1, 'Ai'), (2, 'Risa'), (37, 'Mai'), (32, 'Megumi'), (4, 'Sayumi')]

Or if you are only interested in the values:

>>> s = list(d.get(i) for i in L)
>>> print s
['Ai', 'Risa', 'Mai', 'Megumi', 'Sayumi']

Hope that helps!

Upvotes: 5

AndiDog
AndiDog

Reputation: 70108

In Python 3.1, you could use the OrderedDict class:

from collections import OrderedDict

l = [1, 2, 37, 32, 4]
d = {
    32: 'Megumi', 
    1: 'Ai',
    2: 'Risa',
    3: 'Eri', 
    4: 'Sayumi', 
    37: 'Mai'
}

def myindex(element):
    try:
        return l.index(element)
    except ValueError:
        return -1 # nonexisting keys are appended to the beginning of the list

od = OrderedDict(sorted(d.items(), key = lambda t: myindex(t[0])))

print(od)

As I didn't know what you want to do with keys that aren't in the list, I just return -1 in that case, meaning those elements are prepended to the list somehow (i.e. in non-stable order).

My example will print

OrderedDict([(3, 'Eri'), (1, 'Ai'), (2, 'Risa'), (37, 'Mai'), (32, 'Megumi'), (4, 'Sayumi')])

Upvotes: 0

John La Rooy
John La Rooy

Reputation: 304137

Don't shadow the builtins dict and list

>>> L = [1, 2, 37, 32, 4, 3]
>>> D = {
...     32: 'Megumi',
...     1: 'Ai',
...     2: 'Risa',
...     3: 'Eri',
...     4: 'Sayumi',
...     37: 'Mai'
... }

# Seems roundabout to use sorted here
# This causes an index error for keys in D that are not listed in L
>>> sorted(D.items(), key=lambda x:L.index(x[0]))
[(1, 'Ai'), (2, 'Risa'), (37, 'Mai'), (32, 'Megumi'), (4, 'Sayumi'), (3, 'Eri')]
>>>

# I think this is more direct than using sorted.
# This also ignores/skips keys in D that aren't listed in L
>>> [(i,D[i]) for i in L]
[(1, 'Ai'), (2, 'Risa'), (37, 'Mai'), (32, 'Megumi'), (4, 'Sayumi'), (3, 'Eri')]
>>>

Upvotes: 7

Alexander Lebedev
Alexander Lebedev

Reputation: 6044

Sorted dict is in fact a list of 2-tuples, because in Python 2.x there're no ordered dictionaty built-in. You almost got the solution, just add a value lookup after sorting keys:

[(k,dict[k]) for k in sorted(dict.keys(), key=list.index)]

But this fails when a key is not in list. Let's add a modification to put all such values at the end of sort, ordered by value:

def _index(x): # Allow non-full key list to be used in sorting
    try: return (list.index(x), x)
    except ValueError: return (sys.maxint, x)

[(k,dict[k]) for k in sorted(dict.keys(), key=_index)]

Upvotes: 1

Mark Byers
Mark Byers

Reputation: 837996

You can't sort a dictionary because a dictionary is not ordered.

What you can do instead is:

  • Get all the key-value pairs out of the dictionary, sort them and put them into a list or
  • What you are already doing: keep a sorted list of the keys and use the dictionary when you need the value corresponding to a key.

Upvotes: 1

Related Questions