5

I have looked for ages and have found no actual answers because I can't see any that start with an ascending key and then by a descending value.

An example to make it clearer:

d = {'banana':3, 'orange':5, 'apple':5}
out: [('apple', 5), ('orange', 5), ('banana', 3)]

After doing some research I arrived at something like:

sorted(d.items(), key=operator.itemgetter(1,0), reverse=True)
out: [('orange', 5), ('apple', 5), ('banana', 3)]

This is because it's reverse-sorting both the value and the key. I need the key to be un-reversed.

I'd really appreciate some help here. Thanks in advance!

Rlz
  • 1,649
  • 2
  • 13
  • 36
  • You can't sort dictionaries, they aren't ordered. – jonrsharpe Feb 21 '16 at 17:19
  • 1
    You can use `OrderedDict`. – Avihoo Mamka Feb 21 '16 at 17:20
  • I am trying to sort by both key and value @AvihooMamka – Rlz Feb 21 '16 at 17:20
  • If you think you know a way to do it please put it in the format of an answer. Thanks. @jonrsharpe – Rlz Feb 21 '16 at 17:21
  • ...I've literally just told you you *can't* do it. You could use an `OrderedDict`, instead, so why don't you go and look into that? – jonrsharpe Feb 21 '16 at 17:24
  • 1
    Even if you stored data in a sorted order, it's going to get mixed up again, like people have already said the dicts don't store order. Just try printing a dict a few times and notice how the contents are printed in different order each time. OrderedDict may help like previously stated and ias already well covered. http://stackoverflow.com/questions/9001509/how-can-i-sort-a-dictionary-by-key?rq=1 – Chris Feb 21 '16 at 17:28
  • 5
    notice that a dictionary cannot have the same key multiples time so your example with 1 and 12 multiples times is not posible, you will get `{8: 3, 1: 4, 12: 5, 5: 3}` because inserting a key already there only rewrite the previous value – Copperfield Feb 21 '16 at 17:43
  • Ok I have made an edit does this help? – Rlz Feb 21 '16 at 17:46
  • Not really; it's still not a valid dictionary, dictionaries still aren't ordered and this still isn't a code-writing service (where's *your* attempt?) – jonrsharpe Feb 21 '16 at 17:50
  • This has been asked innumerable number of times and the answer remains the same. – Eli Korvigo Feb 21 '16 at 17:50

2 Answers2

3

What you are asking is not possible as stated. Not only are dictionaries unordered (which can be overcome with an OrderedDict), but their keys are unique, which means the idea of sorting by key and then by value is nonsensical.

What you want is to either use a list of tuples instead, or to use an OrderedDict in which the values are lists (so that they can have multiple values and be sorted.)

List of tuples:

x = [(1,7), (5,3), (8,3), (1,4), (12,4), (12,7), (12,5)]
x.sort(key=itemgetter(1), reverse=True)
x.sort(key=itemgetter(0))
# result: [(1, 7), (1, 4), (5, 3), (8, 3), (12, 7), (12, 5), (12, 4)]
Jason S
  • 13,538
  • 2
  • 37
  • 42
2

Like others say, keys are unique in dictionaries, so if you sort d.items() by key, there is no more sorting to do. But what if you want to sort first by descending value and then by ascending key?

out = list(sorted(d.items(), key=(lambda item: (-item[1],item[0]))))

Result: [('apple', 5), ('orange', 5), ('banana', 3)]

Explanation: When sorting tuples, the elements are considered in sequence. In the expression above I have used a new tuple derived from the original tuple item, to flip the order and also flip the sign of the number.

Elias Hasle
  • 637
  • 7
  • 15