2

I'm relatively new to programming, and I want to sort a 2-D array (lists as they're called in Python) by the value of all the items in each sub-array. For example:

pop = [[1,5,3],[1,1,1],[7,5,8],[2,5,4]]

The sum of the first element of pop would be 9, because 1 + 5 + 3 = 9. The sum of the second would be 3, because 1 + 1 + 1 = 3, and so on.

I want to rearrange this so the new order would be:

newPop = [pop[1], pop[0], pop[3], pop[2]]

How would I do this?

Note: I don't want to sort the elements each sub-array, but sort according to the sum of all the numbers in each sub-array.

Student Loans
  • 303
  • 1
  • 4
  • 10

3 Answers3

4

You can use sorted():

>>> pop = [[1,5,3],[1,1,1],[7,5,8],[2,5,4]]
>>> newPop = sorted(pop, key=sum)
>>> newPop
[[1, 1, 1], [1, 5, 3], [2, 5, 4], [7, 5, 8]]

You can also sort in-place with pop.sort(key=sum). Unless you definitely want to preserve the original list, you should prefer in-pace sorting.

arshajii
  • 127,459
  • 24
  • 238
  • 287
2

Try this:

sorted(pop, key=sum)

Explanation:

  • The sorted() procedure sorts an iterable (a list in this case) in ascending order
  • Optionally, a key parameter can be passed to determine what property of the elements in the list is going to be used for sorting
  • In this case, the property is the sum of each of the elements (which are sublists)

So essentially this is what's happening:

[[1,5,3], [1,1,1], [7,5,8], [2,5,4]]              # original list
[sum([1,5,3]), sum([1,1,1]), sum([7,5,8]), sum([2,5,4])] # key=sum
[9, 3, 20, 11]                                    # apply key
sorted([9, 3, 20, 11])                            # sort
[3, 9, 11, 20]                                    # sorted
[[1,1,1], [1,5,3], [2,5,4], [7,5,8]]              # elements coresponding to keys
Óscar López
  • 232,561
  • 37
  • 312
  • 386
1

@arshajii beat me to the punch, and his answer is good. However, if you would prefer an in-place sort:

>>> pop = [[1,5,3],[1,1,1],[7,5,8],[2,5,4]]
>>> pop.sort(key=sum)
>>> pop
[[1, 1, 1], [1, 5, 3], [2, 5, 4], [7, 5, 8]]

I have to look up Python's sorting algorithm -- I think it's called Timsort, bit I'm pretty sure an in-place sort would be less memory intensive and about the same speed.

Edit: As per this answer, I would definitely recommend x.sort()

If you wanted to sort the lists in a less traditional way, you could write your own function (that takes one parameter.) At risk of starting a flame war, I would heavily advise against lambda.

For example, if you wanted the first number to be weighted more heavily than the second number more heavily than the third number, etc:

>>> def weightedSum(listToSum):
...     ws = 0
...     weight = len(listToSum)
...     for i in listToSum:
...         ws += i * weight
...         weight -= 1
...     return ws
... 
>>> weightedSum([1, 2, 3])
10
>>> 1 * 3 + 2 * 2 + 3 * 1
10
>>> pop
[[1, 5, 3], [1, 1, 1], [7, 5, 8], [2, 5, 4]]
>>> pop.sort(key=weightedSum)
>>> pop
[[1, 1, 1], [1, 5, 3], [2, 5, 4], [7, 5, 8]]
>>> pop += [[1, 3, 8]]
>>> pop.sort(key=weightedSum)
>>> pop
[[1, 1, 1], [1, 5, 3], [1, 3, 8], [2, 5, 4], [7, 5, 8]]
Community
  • 1
  • 1
vroomfondel
  • 3,056
  • 1
  • 21
  • 32