Sorted function referencing keys in a dictionary to define the sort criteria

Asked

Viewed 47 times

1

dict = {'dc':20,'ba':10,'aa':5,'db':30,'za':1}

dict_2 = sorted(dict.items(), key = lambda dict: dict[1], reverse = True)

print(dict_2)

When I place Dict[1] in the function argument I get the following return:

[('db', 30), ('dc', 20), ('ba', 10), ('aa', 5), ('za', 1)]

When I place Dict[0] in the function argument I get the following return:

[('za', 1), ('dc', 20), ('db', 30), ('ba', 10), ('aa', 5)]

From what I understand, if I put dict[1] it starts to sort considering the second letter of the key string and when I put dict[0] it starts to sort considering the first letter of the key string. My question is the following: when I make a reference dict['x'] shouldn’t be returned the value for the key 'x'? In order to sort by the position in the string I shouldn’t have to put dict['x'[0]] or dict['x'[1]]?

1 answer

2


if I put dict[1] it starts sorting considering the second letter of the key string

It’s not like that.


First, let’s see what items() returns:

for item in dict.items():
    print(item, type(item))

Exit:

('dc', 20) <class 'tuple'>
('ba', 10) <class 'tuple'>
('aa', 5) <class 'tuple'>
('db', 30) <class 'tuple'>
('za', 1) <class 'tuple'>

items() returns several tuples, each tuple contains a dictionary key and its respective value.

That is to say, sorted will sort these tuples. And the sort criteria was specified by lambda. So when do I:

lambda dict: dict[1]

I am saying that this is a function that takes a parameter (in this case, called dict) and returns the element that is at position 1.

But as I’m passing several tuples to sorted, then the lambda will receive a tuple as argument, and will take the tuple element that is at position 1. In this case, it will be the value (which in your dictionary, is the 20, 30, etc). You can see:

for item in dict.items():
    print(f'posição zero: {item[0]}, posição 1: {item[1]}')

Exit:

posição zero: dc, posição 1: 20
posição zero: ba, posição 1: 10
posição zero: aa, posição 1: 5
posição zero: db, posição 1: 30
posição zero: za, posição 1: 1

That is, when you use dict[1] in the lambda, is saying to order by values (20, 30, etc), and when you use dict[0], is saying to sort by the keys (aa, ba, etc). And of course, how you used reversed=True, the result will be in nonconsecutive order. And remember that numbers are compared according to their numerical value, and strings, according to alphabetical order (to be more precise, it is in order lexicographical).


That said, I would change the parameter name of the lambda, for dict, besides being one of the functions builtin, still gives the wrong impression that there is a dictionary. There isn’t, because as we’ve seen, at that point we have a tuple containing a key and its value, so switch to something like item, for example.

Anyway, if you want to sort by the first letter of each key, it would have to be something like this:

dict_2 = sorted(dict.items(), key = lambda item: item[0][0], reverse = True)

Remember: item is a tuple containing a key and a value. At zero position item[0] we have the key, which in your case are strings. So to get the first character of this string just do item[0][0].

If you wanted to order by the second character, just change to:

dict_2 = sorted(dict.items(), key = lambda item: item[0][1], reverse = True)
#                                                        ↑
#                                    aqui (1 indica o segundo caractere da string)
  • you are sensational! Thank you so much for the detailed explanation and for dedicating this time to writing it. I’m starting my studies in programming and knowing that this community is so cool and if it helps me a lot to keep learning

Browser other questions tagged

You are not signed in. Login or sign up in order to post.