1

I have a 2d list, in the first part I have a string which represents the measurement number while the 2nd part represents the corresponding numerical measurement. I have attached the list below, and python seems to have ordered it 1,10,11,...,2,3,4 etc.

My question is how do I get it in chronological order? So that PI_1.txt is followed by PI_2.txt and not PI_10.txt

  ['PI_1.txt', 1004.1]
  ['PI_10.txt', 1104.8]
  ['PI_11.txt', 1115.3]
  ['PI_12.txt', 1104.7]
  ['PI_2.txt', 1019.1]
  ['PI_3.txt', 1062.3]
  ['PI_4.txt', 1239.6]
  ['PI_5.txt', 1143.2]
  ['PI_6.txt', 1139.3]
  ['PI_7.txt', 1131.3]
  ['PI_8.txt', 1130.9]
  ['PI_9.txt', 1108.9]

The list is above to make my description a bit simpler.

Thank you!

p.s. I can't change the filenames so they are just integers, as part of my code uses a selection based on whether or not "PI" is included in the filename

  • It's ordered lexicographically, because your measurement numbers are part of a string. You can find a good explanation for this here: https://softwareengineering.stackexchange.com/questions/127639/why-do-some-sorting-methods-sort-by-1-10-2-3/127644. To solve your problem, you'll need some kind of natural sort: https://stackoverflow.com/questions/4836710/is-there-a-built-in-function-for-string-natural-sort – bm13563 Feb 19 '21 at 17:41
  • @jarmod Did you test this? Try `x = ['PI_10.txt', 'PI_3.txt', 'PI_1.txt']` and then `x.sort()` and you'll see how Python orders it by default. – gen_Eric Feb 19 '21 at 17:44
  • @RocketHazmat Yes, Python will sort it that way if you call `sort()` on the populated list. There was no clear indication (such as actual code) that the OP populated the list a certain way and then called sort() on it but, fair comment, one could assume that (but I always prefer to see actual code, rather than assume something). – jarmod Feb 19 '21 at 17:52
  • Aside from a custom sort, if you're going to index between 10 and 99 filenames then it's simple to make your index format `%02d` rather than `%d` (or for a range 0-999, use `%03d`). Then you essentially get sorting for free with `list.sort()`. – jarmod Feb 19 '21 at 17:54
  • Thank you all for the help !! – Charlotte Lawton Feb 19 '21 at 18:19

3 Answers3

2

You could sort with a key:

listy.sort(key=lambda x: int(x[0].split('.')[0].split('_')[1]))
whackamadoodle3000
  • 6,684
  • 4
  • 27
  • 44
2

If you want to sort the list in-place (as opposed to returning a sorted copy of the list) and the files are consistently named, you can use the following code which uses a key function to determine the order.


data = [
    ['PI_1.txt', 1004.1],
    ['PI_10.txt', 1104.8],
    ['PI_11.txt', 1115.3],
    ['PI_12.txt', 1104.7],
    ['PI_2.txt', 1019.1],
    ['PI_3.txt', 1062.3],
    ['PI_4.txt', 1239.6],
    ['PI_5.txt', 1143.2],
    ['PI_6.txt', 1139.3],
    ['PI_7.txt', 1131.3],
    ['PI_8.txt', 1130.9],
    ['PI_9.txt', 1108.9]
]


data.sort(key=lambda d: int(d[0][3:-4]))

This code accesses the first item in the sublist, selects everything between the 3rd and last 4 characters, converts it to an integer, and then uses that value to order the 2-d list.

Kapocsi
  • 922
  • 6
  • 17
0

For this kind of task, I like to use the natsort library to handle naturally sorting the numbers with operator.itemgetter to help with identifying the element by which the nested list should be sorted. With that all together, you can easily sort your 2D list like this:

#!/usr/bin/env python
from operator import itemgetter
from natsort import natsorted
from pprint import pprint as pp

d = [['PI_1.txt', 1004.1],
     ['PI_10.txt', 1104.8],
     ['PI_11.txt', 1115.3],
     ['PI_12.txt', 1104.7],
     ['PI_2.txt', 1019.1],
     ['PI_3.txt', 1062.3],
     ['PI_4.txt', 1239.6],
     ['PI_5.txt', 1143.2],
     ['PI_6.txt', 1139.3],
     ['PI_7.txt', 1131.3],
     ['PI_8.txt', 1130.9],
     ['PI_9.txt', 1108.9]]

print('Before: ')
pp(d)

print('\nAfter: ')
d = natsorted(d, key=itemgetter(0))
pp(d)

The resultant output looks like this:

Before:
[['PI_1.txt', 1004.1],
 ['PI_10.txt', 1104.8],
 ['PI_11.txt', 1115.3],
 ['PI_12.txt', 1104.7],
 ['PI_2.txt', 1019.1],
 ['PI_3.txt', 1062.3],
 ['PI_4.txt', 1239.6],
 ['PI_5.txt', 1143.2],
 ['PI_6.txt', 1139.3],
 ['PI_7.txt', 1131.3],
 ['PI_8.txt', 1130.9],
 ['PI_9.txt', 1108.9]]

After:
[['PI_1.txt', 1004.1],
 ['PI_2.txt', 1019.1],
 ['PI_3.txt', 1062.3],
 ['PI_4.txt', 1239.6],
 ['PI_5.txt', 1143.2],
 ['PI_6.txt', 1139.3],
 ['PI_7.txt', 1131.3],
 ['PI_8.txt', 1130.9],
 ['PI_9.txt', 1108.9],
 ['PI_10.txt', 1104.8],
 ['PI_11.txt', 1115.3],
 ['PI_12.txt', 1104.7]]
drmrgd
  • 733
  • 5
  • 17