Home > front end >  Is there a python function for sorting a 2D array based on both elements in the nested array?
Is there a python function for sorting a 2D array based on both elements in the nested array?

Time:10-15

So I have a list that looks like this: people_list = [[str name, int numerical value]] where there are n amounts of lists inside of people_list. With actual data, it would look like this: people_list = [['jim', 30000], ['james', 30000]]. I need to sort this list first based on the numerical value in each nested list, so sorted based on people_list[i][1] where i is the nth nested list, and the entire people_list needs to be sorted from highest to lowest numerical value. Then if there are any ties in the numerical value I need to sort the tied lists alphabetically based on the name, so people_list[i][0].

I tried the code below to sort, but the output was not exactly how I needed it, and I haven't found any other resources online to get it to sort how I need to.

people_list = [['jim', 33000], ['james', 22000], ['john', 33000], ['zack', 10000]]
sorted_by_int_then_name = sorted(people_list, key=lambda person: (person[1], person[0]), reverse=True)

The output for this code is:

>>> sorted_by_int_then_name
[['john', 33000], ['jim', 33000], ['james', 22000], ['zack', 10000]]

This is sorted correctly numerically, but the names are not sorted alphabetically like I need them to be. I think the issue I'm having might be because I'm using the reverse=True parameter, but if I don't include that parameter then the list is sorted from lowest numerical value to highest. The output I am looking for would be this:

>>> sorted_by_int_then_name
[['jim', 33000], ['john', 33000], ['james', 22000], ['zack', 10000]]

How can I properly sort by numerical value for people_list[i][1] and then by people_list[i][0] whenever the numerical value is tied?

I am running this code using python version 3.8.10 on Ubuntu 20.04.3 LTS

CodePudding user response:

One approach is to multiply the integer by -1 instead of using reverse=True:

people_array = [['jim', 33000], ['james', 22000], ['john', 33000], ['zack', 10000]]
sorted_by_int_then_name = sorted(people_array, key=lambda person: (-1 * person[1], person[0]))
print(sorted_by_int_then_name)

Output

[['jim', 33000], ['john', 33000], ['james', 22000], ['zack', 10000]]

As an alternative, and taking advantage of the fact that sorted is stable, use a two-pass sort:

from operator import itemgetter

people_array = [['jim', 33000], ['james', 22000], ['john', 33000], ['zack', 10000]]
sorted_by_int_then_name = sorted(people_array, key=itemgetter(0))
sorted_by_int_then_name.sort(key=itemgetter(1), reverse=True)
print(sorted_by_int_then_name)

Output

[['jim', 33000], ['john', 33000], ['james', 22000], ['zack', 10000]]

The two-pass sort can be faster, see this.

  • Related