How to sort keys only with same values?

3.5k views Asked by At

For example, i have a dictionary:

Edern 38
Pellam 34
Ban 32
Lionel 30
Geraint 30
Brangaine 28
Erec 28
Guiron 28
Fisher 28
Elyan 28
Segwarides 26

In this case output will be:

Edern 38
Pellam 34
Ban 32
Geraint 30
Lionel 30
Brangaine 28
Elyan 28
Erec 28
Fisher 28
Guiron 28
Segwarides 26

i want to sort keys with the same values in alphabetical order, but don't touch elements with different keys? How to realize this?

2

There are 2 answers

1
Kevin On BEST ANSWER

If you represent your name-number pairs as a list of two-item tuples, you can use groupby to clump similar-numbered items together, and sort each group internally without affecting group order.

import itertools

items = [
    ("Edern", 38),
    ("Pellam", 34),
    ("Ban", 32),
    ("Lionel", 30),
    ("Geraint", 30),
    ("Brangaine", 28),
    ("Erec", 28),
    ("Guiron", 28),
    ("Fisher", 28),
    ("Elyan", 28),
    ("Segwarides", 26)
]

result = []
for k,v in itertools.groupby(items, lambda item: item[1]):
    result.extend(sorted(v))

print result

Result:

[
('Edern', 38), 
('Pellam', 34), 
('Ban', 32), 
('Geraint', 30), 
('Lionel', 30), 
('Brangaine', 28), 
('Elyan', 28), 
('Erec', 28), 
('Fisher', 28), 
('Guiron', 28), 
('Segwarides', 26)
]

...And if you really need these items in dict form, you can make an OrderedDict out of them, like so:

from collections import OrderedDict
d = OrderedDict(result)
0
inspectorG4dget On

It seems that you want to sort by decreasing numeric value. So this should work for you:

d = {'Edern':38,
     'Pellam':34,
     'Ban':32,
     'Lionel':30,
     'Geraint':30,
     'Brangaine':28,
     'Erec':28,
     'Guiron':28,
     'Fisher':28,
     'Elyan':28,
     'Segwarides':26}

# build a dictionary that maps the numbers to all the keys that have that value
scored = {}
for k,v in d.items():
    if v not in scored:
        scored[v] = []
    scored[v].append(k)

for k in sorted(scored, reverse=True):
    for v in sorted(scored[k]):
        print("{} {}".format(v, k))

Output:

Edern 38
Pellam 34
Ban 32
Geraint 30
Lionel 30
Brangaine 28
Elyan 28
Erec 28
Fisher 28
Guiron 28
Segwarides 26

Of course, there's a one-liner for this:

for k,v in sorted(list(d.items()), key=lambda t: (-1*t[1], t[0])):
    print("{} {}".format(k, v))

Output:

Edern 38
Pellam 34
Ban 32
Geraint 30
Lionel 30
Brangaine 28
Elyan 28
Erec 28
Fisher 28
Guiron 28
Segwarides 26