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
4
  • 1
    what was the error the last line gave you? I ran your code and got your desired sorted output with no error. Commented Apr 19, 2017 at 2:13
  • You're right! I had forgotten that x.sort() sorts the array in place, so it was outputting None and causing parts of my code to spit out garbage. Thanks! Commented Apr 19, 2017 at 2:24
  • Ah, yes, I know the feeling! good to hear you figured it out, glad to help. cheers! Commented Apr 19, 2017 at 2:26
  • Possible duplicate of Does Python have a built in function for string natural sort? Commented Apr 19, 2017 at 2:40

4 Answers 4

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']
Sign up to request clarification or add additional context in comments.

Comments

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']]

Comments

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']

Comments

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.