2

Currently, I am trying to learn more about how to utilize comprehensions. However, I am stuck with this problem I have right now.

The dictionary I have:

d =  {'Second': {('Carrie', 3), ('Diane', 3), ('Bob', 3)},
      'Third': {('Alan', 2), ('Diane', 5)},
      'Fourth': {('Carrie', 2), ('Alan', 5)},
      'First': {('Bob', 5), ('Carrie', 5), ('Alan', 1), ('Diane', 1)} }

I am trying to sort it by the number of values each key has so it would look like this when returned. If the key both have the same amount of values, it would be sorted alphabetically.

Desired Output:

['First', 'Second', 'Fourth', 'Third']

What I have so far however, I am unsure how to sort by the len of the values :

d = {'Second': {('Carrie', 3), ('Diane', 3), ('Bob', 3)}, 'Third': {('Alan', 2), ('Diane', 5)}, 'Fourth': {('Carrie', 2), ('Alan', 5)}, 'First': {('Bob', 5), ('Carrie', 5), ('Alan', 1), ('Diane', 1)} }

def sorting(d):
    return sorted([key for key, value in db.items(), key = lambda x: -len( )
cs95
  • 379,657
  • 97
  • 704
  • 746
  • 1
    Possible duplicate of https://stackoverflow.com/questions/613183/how-do-i-sort-a-dictionary-by-value – hqkhan Jan 18 '19 at 01:47
  • 1
    There is no need for a comprehension construct here, you are sorting *keys*, iterating over a dictionary iterates over it's keys already: `sorted(d, key=lambda k:(-len(d[k]), k))` suffices – juanpa.arrivillaga Jan 18 '19 at 02:18
  • 1
    Please do not vandalize your posts. Your edit invalidates the answers posted below – adiga Jan 19 '19 at 06:56

3 Answers3

1

Create a dictionary mapping keys to their length, and then call sorted on that.

d2 = {k: len(d[k]) for k in d}
sorted(d2, key=d2.get, reverse=True)
# ['First', 'Second', 'Third', 'Fourth']

Using a lambda would eliminate the need for a mapping, but would also mean the key is a lambda function, ... but here it is:

sorted(d, key=lambda k: (len(d[k]), k), reverse=True)
# ['First', 'Second', 'Third', 'Fourth']

Here, the key callback returns a tuple (len(d[k]), k) ensuring that sorting is first done by the length, and then in alphabetical order.


As a silly one-liner, you can do this:

(lambda d: sorted(d, key=d.get, reverse=True))({k: len(d[k]) for k in d}) 
# ['First', 'Second', 'Third', 'Fourth']

This is just a stand-in for assignment expressions, I'm waiting for python-3.8.

cs95
  • 379,657
  • 97
  • 704
  • 746
0

You can use the reverse parameter in the sorted function:

results = [a for a, _ in sorted(d.items(), key=lambda x:len(x[-1]), reverse=True)]

Output:

['First', 'Second', 'Third', 'Fourth']
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
0

Just have a lambda that returns two values. The length of the value, and a list of negative ord's of all the characters in the key to negate the reverse = True for alphabetical sorting.

print(sorted(d.keys(), key = lambda a: (len(d[a]), [-ord(c.lower()) for c in a]), reverse = True))
#['First', 'Second', 'Fourth', 'Third']
Joyal Mathew
  • 614
  • 7
  • 24