Sorting a dictionary in Python with several parameters? - python

I have a Dictionary that, when printed with each key and value, looks like this:
a__________a_______:1
___________________:2
_______________a___:1
___________a____a__:1
___________a_a_____:1
__________a__a_____:1
________a______a___:1
____a____________a_:1
_____a_____________:1
__a_______a________:1
__________a________:2
____________a____a_:2
_______a___________:1
I am trying to sort the dictionary so that it is sorted by value, which is pretty simple. However, each group within the same value has to be sorted by the number of '_'s; and if the number of underscores is the same, then they are sorted alphabetically. So, after sorting, it would look like this:
___________a____a__:1
___________a_a_____:1
__________a__a_____:1
________a______a___:1
____a____________a_:1
__a_______a________:1
a__________a_______:1
_______________a___:1
_______a___________:1
_____a_____________:1
____________a____a_:2
__________a________:2
___________________:2
I understand sorting by value. I am just having trouble being able to sort it within each value group like I stated.

You can sort using a tuple in order of your desired means of ordering:
res = dict(sorted(d.items(), key=lambda it: (it[1], it[0].count('_'), it[0])))

Related

Is it possible to sort a list of strings that represents Filipino numbers

list = [dalawa, tatlo, apat, siyam, isa] and is there a way to sort this to list = [isa, dalawa, tatlo, apat, siyam]. I an new in python so I don't have any idea about this.
The python sort() method will sort a list in alphabetical order.
What you can do is assign the value of each filipino number as a dictionary, and then sort it according to value.
That should be done as so: (I'm making up the values)
list = {"dalawa":2, "tatlo":3, "apat":4, "siyam":5, "isa":1}
# look up lambda functions in order to better understand the below functionality.
# In short what this does is, return to the sorted function the values of keys in the above dictionary and telling it to sort by them and not by the actual via resetting the key parameter to the lambda function.
result = sorted(list, key=lambda x:list[x[0]])

How to find maximum element from a list and its index?

I have a list with ordered dictionaries. These ordered dictionaries have different sizes and can also have the same size(for example, 10 dictionaries can have the length of 30 and 20 dictionaries can have the length of 32). I want to find the maximum number of items a dictionary from the list has. I have tried this, which gets me the correct maximum length:
maximum_len= max(len(dictionary_item) for dictionary_item in item_list)
But how can I find the dictionary fields for which the maximum_len is given? Say that the maximum_len is 30, I want to also have the dictionary with the 30 keys printed. It can be any dictionary with the size 30, not a specific one. I just need the keys of that dictionary.
Well you can always use filter:
output_dics=filter((lambda x: len(x)==maximum_len),item_list)
then you have all the dictionarys that satisfies the condition , pick a random one or the first one
Don't know if this is the easiest or most elegant way to do it but you could just write a simple function that returns 2 values, the max_length you already calculated but also the dict that you can get via the .index method and the max_length of the object you were searching for.
im talking about something like this:
def get_max(list_of_dict):
plot = []
for dict_index, dictionary in enumerate(list_of_dict):
plot.append(len(dictionary))
return max(plot), list_of_dict[plot.index(max(plot))]
maximum_len, max_dict = get_max(test)
tested it, works for my case, although i have just made myself a testlist with just 5 dicts of different length.
EDIT:
changed variable "dict" to "dictionary" to prevent it shadowing from outer scope.

Workaround for creating a sorted list of dictionaries, without the sorted() function

You apparently can't sort a dictionary without using the sorted() function.
So, is there a workaround to that? (The reason I don't use the sorted() function is that this is for a specific school project.)
In the list of dictionaries, each dictionary contains keys like "name", "price" and many more.
Small example dictionary list:
games = [
{"name":"counterstrike", "price":15, "rating":98},
{"name":"teamfortress2", "price":0, "rating":95},
{"name":"half-life", "price":9, "rating":99}
]
I need to sort it on, for example, the highest price, but then still be able to access all the other keys/values.
The furthest I got to that was so that it took all the names, and sorted that using merge sort. But then I only had the "name" of it, and not the "price" etc.
So, can I maybe sort a dictionary by "price" by making a list/tuple out of it or something, sort that using an algorithm (quicksort? merge sort?), then put it back as a list of the now sorted dictionaries?
You could decorate each game with the desired key and a tie-breaker, then sort and finally undecorate.
Sort by name:
decorated = [(g['name'], i, g) for i, g in enumerate(games)]
mysort(decorated)
games = [d[2] for d in decorated]
Sort by price (highest to lowest)
decorated = [(-g['price'], i, g) for i, g in enumerate(games)]
mysort(decorated)
games = [d[2] for d in decorated]
The tie-breaker is needed to avoid the dictionaries getting compared, which isn't allowed (would cause an error). I use the original index as tie-breaker, which additionally makes the sorting stable, regardless of sorting algorithm.

How can i use the sort function if i want to sort ascending by a criterion and descending by another criterion?

I am trying to implement the A* algorithm in Python as a learning exercise. I have a list of nodes, called open, that contains strings that represent the names of graph nodes. Example: open["node_a", "node_b", "node_c"]. I also have two defaultdict dictionaries, f_estim and g, that contain values like {"name_of_node" : integer_representing_a_certain_cost_associated_to_the_node}. I am required to sort the open list ascending by the value associated in f_estim, and if that value is equal for two nodes, descending according to the value in g. I am sorting ascending like so: open.sort(key=lambda node: f_estim[node]). How can i also sort descending when reaching two equal values? I could not find the answer in the documentation of the sort function. Thank you!
You could do something like this:
open.sort(key=lambda node: (f_estim[node], -g[node]))

Python Sorting 2D List with custom Key

So I have a 2D list and want to sort it using a second file of keys. Does anyone know how I would go about doing that?
Heres an example input:
And here is an example input file:
first_nm,last_nm,gender,cwid,cred_hrs,qual_pts,gpa
John,Roe,M,44444444,40,150,3.75
Jane,Roe,F,66666666,100,260,2.6
John,Doe,M,22222222,50,140,2.8
Jane,Doe,F,88888888,80,280,3.5
Penny,Lowe,F,55555555,40,140,3.5
Lenny,Lowe,M,11111111,100,280,2.8
Denny,Lowe,M,99999999,80,260,3.25
Benny,Lowe,M,77777777,120,90,0.75
Jenny,Lowe,F,33333333,50,90,1.8
Zoe,Coe,F,0,50,130,2.6
Here are the keys to sort it(there could be more or less, depending on how you want to sort it)
gender,ascend,string
gpa,descend,float
last_nm,ascend,string
And here would be the output for that input and keys:
first_nm,last_nm,gender,cwid,cred_hrs,qual_pts,gpa
Jane,Doe,F,88888888,80,280,3.5
Penny,Lowe,F,55555555,40,140,3.5
Zoe,Coe,F,00000000,50,130,2.6
Jane,Roe,F,66666666,100,260,2.6
Jenny,Lowe,F,33333333,50,90,1.8
John,Roe,M,44444444,40,150,3.75
Denny,Lowe,M,99999999,80,260,3.25
John,Doe,M,22222222,50,140,2.8
Lenny,Lowe,M,11111111,100,280,2.8
Benny,Lowe,M,77777777,120,90,0.75
I was thinking of just using the built in sort() but was not sure if I would be able to use it if I am sorting 3 different times. I think I would have to sort backwards? (last_nm, then gpa, then gender)
You can return a tuple from your key function to create complex sorts. And as a quick trick, multiply numeric values by -1 for a reverse sort. Your example would look something like this:
lists.sort(key = lambda x: (x[2], x[6] * -1, x[1]))
The list sort() method takes a boolean parameter reverse, but it applies to the whole key; you can't say that you want some parts of the key to use ascending sort and others to use descending. Sadly, there isn't a simple way to extend g.d.d.c's trick of multiplying by -1 to non-numeric data.
So if you need to handle arbitrary combinations of ascending and descending then yes, you will have to sort multiple times, working backwards over your list of keys, like you mention in your question. The built-in Python sorting algorithm, timsort, is a stable sort, which means each time you sort your 2D list with a different key the previous sort results won't get scrambled.

Categories