2

So I have a list of string paths:

x = ['../../scene/temp_5a/458754/1_car.png',
     '../../scene/temp_5a/458754/2_car.png',
     '../../scene/temp_5a/458754/10_car.png',
     '../../scene/temp_5a/458754/15_car.png',
     '../../scene/temp_5a/458754/3_car.png']

And I need to sort it by the number in front of _car. Does anyone know of a quick way to do this?

I currently have this but it seems like the split is getting all the digits. I only want to get the digit in front in front of _car.

def atoi(text):
    return int(text) if text.isdigit() else text

def natural_keys(text):
    return [ atoi(c) for c in re.split('(\d+)', text) ]

x.sort(key=natural_keys) # gives an error
Jun Kim
  • 98
  • 1
  • 4
jlcv
  • 1,688
  • 5
  • 21
  • 50

4 Answers4

1

My way is to split the string and use the number in front of _car as key to make comparisons.

>>> x = [
...     '../../scene/temp_5a/458754/1_car.png',
...     '../../scene/temp_5a/458754/2_car.png',
...     '../../scene/temp_5a/458754/10_car.png',
...     '../../scene/temp_5a/458754/15_car.png',
...     '../../scene/temp_5a/458754/3_car.png']
>>>
>>> sorted(x,key=lambda i: int(i.split('/')[-1].split('_')[0]))
[[1, '../../scene/temp_5a/458754/1_car.png'], [2, '../../scene/temp_5a/458754/2_car.png'], [3, '../../scene/temp_5a/458754/3_car.png'], [10, '../../scene/temp_5a/458754/10_car.png'], [15, '../../scene/temp_5a/458754/15_car.png']]
McGrady
  • 10,869
  • 13
  • 47
  • 69
1
x = ['../../scene/temp_5a/458754/1_car.png',
'../../scene/temp_5a/458754/2_car.png',
'../../scene/temp_5a/458754/10_car.png',
'../../scene/temp_5a/458754/15_car.png',
'../../scene/temp_5a/458754/3_car.png']
sorted(x,key=lambda x: int(x.split('/')[-1].split('_car')[0]))

Out[118]: 
['../../scene/temp_5a/458754/1_car.png',
 '../../scene/temp_5a/458754/2_car.png',
 '../../scene/temp_5a/458754/3_car.png',
 '../../scene/temp_5a/458754/10_car.png',
 '../../scene/temp_5a/458754/15_car.png']
Allen Qin
  • 19,507
  • 8
  • 51
  • 67
1

I'm not sure why your regex gave you an error, it worked for me. Maybe try a different regex?

Replacing yours with r'.*\/([^_]*)_.*' may also work:

x = ['../../scene/temp_5a/458754/1_car.png',
'../../scene/temp_5a/458754/2_car.png',
'../../scene/temp_5a/458754/10_car.png',
'../../scene/temp_5a/458754/15_car.png',
'../../scene/temp_5a/458754/3_car.png']

def atoi(text):
return int(text) if text.isdigit() else text

def natural_keys(text):
    return [ atoi(c) for c in re.split(r'.*\/([^_]*)_.*', text) ]

x.sort(key=natural_keys)
print x

output:

['../../scene/temp_5a/458754/1_car.png',  
'../../scene/temp_5a/458754/2_car.png', 
'../../scene/temp_5a/458754/3_car.png', 
'../../scene/temp_5a/458754/10_car.png', 
'../../scene/temp_5a/458754/15_car.png']
1

String matching is what regex does. Requires very little regex.

import re

x = ['../../scene/temp_5a/458754/1_car.png',
     '../../scene/temp_5a/458754/2_car.png',
     '../../scene/temp_5a/458754/10_car.png',
     '../../scene/temp_5a/458754/15_car.png',
     '../../scene/temp_5a/458754/3_car.png']


def file_matcher(files):
    numbers = []
    for f in files:
        match = re.search(r'([0-9]+)_car.png', f)
        numbers.append(match.group(1))
    return numbers

print file_matcher(x)
Garrett Kadillak
  • 1,026
  • 9
  • 18