Heba Masarwa
Heba Masarwa

Reputation: 57

How to order values in a dictionary in a lexicography order?

I have this code here:

def most_popular_book(book_loans):
    vBL = book_loans.values()
    kBL = book_loans.keys()
    items = book_loans.items()
    print items
    kBL = sorted(kBL, key=str.lower)
    mvBL = max(vBL)
    for key,vaule in items:
        if vaule == mvBL:
            return key

my goal with this code is to get the key with the biggest value, and if 2 keys have the same values then choose the one that comes first in a lexicography order.

now the first part of the code works fine! however I am having trouble with the second part. I read some code on the subject but I haven't been able to find a way to make it work.

example for how the code should work:

print most_popular_book({'harry potter':['yossi','adam'], 
'lilo and stich':['yossi', "adam"], 'catch-22':['adam'] })

'harry potter'

(it should print harry potter) but my code prints 'lilo and stich'

another example:

{'the little prince': ['yossi'], 'harry potter': ['yossi', 'assaf'], 
 'catch-22': ['yossi', 'dana']}

'catch-22'

(this output is working correctly)

Upvotes: 2

Views: 94

Answers (2)

Dani Mesejo
Dani Mesejo

Reputation: 61930

You could use min if you only want the most popular book:

def most_popular_book(books):
    result, _ = min(books.items(), key=lambda x: (-len(x[1]), x[0]))
    return result


print(most_popular_book({'harry potter': ['yossi', 'adam'],
                         'lilo and stich': ['yossi', "adam"], 'catch-22': ['adam']}))
print(most_popular_book({'the little prince': ['yossi'], 'harry potter': ['yossi', 'assaf'],
                         'catch-22': ['yossi', 'dana']}))

Output

harry potter
catch-22

The idea is the same as in the answer of @PatrickArtner, the only difference being the sorted is O(nlogn) and min is O(n). No need to sort the list, only to find the minimum.

Upvotes: 1

Patrick Artner
Patrick Artner

Reputation: 51683

You can get the fully sorted list by:

fancy = sorted( book_loans.items(), key = lambda x:(-len(x[1]), x[0]))

and takte the first one.

It works by defining a tuple as sort-criteria - tuples are sorted by 1st value, then 2nd value if 1st value draws etc.

Sorting by -len() "inverts" it (you could also specify the reverse=True param to sorting - either one works.

fancy = sorted( {'harry potter':['yossi','adam'], 'lilo and stich':['yossi', "adam"],
                 'catch-22':['adam'] }.items(), key = lambda x:(-len(x[1]), x[0])) 

print(fancy)
print(fancy[0][0])

Output:

[('harry potter', ['yossi', 'adam']), ('lilo and stich', ['yossi', 'adam']),
 ('catch-22', ['adam'])]

harry potter

Upvotes: 3

Related Questions