2015-10-15 2 views
3

У меня есть каталог с jpg и другими файлами в нем, все jpg-файлы имеют имена файлов с номерами в них. Некоторые могут иметь дополнительные строки в имени файла.Сортировка имен файлов в каталоге в порядке возрастания

Например.

01.jpg 

Или это может быть

Picture 03.jpg 

В Python Мне нужен список всех JPGs в порядке возрастания. Вот фрагмент кода для этого

import os 
import numpy as np 

myimages = [] #list of image filenames 
dirFiles = os.listdir('.') #list of directory files 
dirFiles.sort() #good initial sort but doesnt sort numerically very well 
sorted(dirFiles) #sort numerically in ascending order 

for files in dirFiles: #filter out all non jpgs 
    if '.jpg' in files: 
     myimages.append(files) 
print len(myimages) 
print myimages 

Что я получаю это

['0.jpg', '1.jpg', '10.jpg', '11.jpg', '12.jpg', '13.jpg', '14.jpg', 
'15.jpg', '16.jpg', '17.jpg', '18.jpg', '19.jpg', '2.jpg', '20.jpg', 
'21.jpg', '22.jpg', '23.jpg', '24.jpg', '25.jpg', '26.jpg', '27.jpg', 
'28.jpg', '29.jpg', '3.jpg', '30.jpg', '31.jpg', '32.jpg', '33.jpg', 
'34.jpg', '35.jpg', '36.jpg', '37.jpg', '4.jpg', '5.jpg', '6.jpg', 
'7.jpg', '8.jpg', '9.jpg'] 

Очевидно, что он сортирует вслепую наиболее значительное число первых. Я попытался использовать sorted(), поскольку вы можете видеть, что он исправит это, но это не имеет значения.

+0

'fnames = sorted ([fname для fname в os.listdir ('.'), Если fname.endswith ('. Jpg')], key = lambda f: int (f.rsplit (os.path.extsep, 1) [0] .rsplit (None, 1) [- 1])) ' – inspectorG4dget

+0

Это потому, что элементы' list' являются 'strings'. –

+2

[Сортировка списка, содержащего буквенно-цифровые строки] (http://stackoverflow.com/questions/19366517/sorting-in-python-how-to-sort-a-list-containing-alphanumeric-values) – sam

ответ

7

Предполагая, что есть только один номер в имени каждого файла:

>>> dirFiles = ['Picture 03.jpg', '02.jpg', '1.jpg'] 
>>> dirFiles.sort(key=lambda f: int(filter(str.isdigit, f))) 
>>> dirFiles 
['1.jpg', '02.jpg', 'Picture 03.jpg'] 
+0

Работает тоже! Очень чисто, мне нравится ваше решение. Но это не удастся, если по какой-либо причине список имеет элемент, в котором нет чисел. Но я просто сделал все, чтобы сделать вид в myimages [], который будет иметь номер в названии наверняка. – user3474042

+0

@ user3474042 Да, если все jpegs имеют номера, то это работает. В противном случае, возможно, используйте 'int (filter (str.isdigit, f) или -1)) '(это приводит к тому, что имена файлов с цифрой меньше). Btw, проверьте модуль 'glob', который позволяет вам напрямую запрашивать файлы' * .jpg'. –

+4

Лямбда для python 3 становится более уродливой: 'lambda f: int (''. Join (filter (str.isdigit, f))))' (иначе он будет жаловаться, что аргумент * int() должен быть строкой, a байт-подобный объект или число, а не «фильтр» * ... Я скучаю по утиному рубину ruby ​​...) – boiko

0

есть модуль natsorted. Просто сделайте pip install natsorted.

>>> from natsort import 
>>> ll = ['Picture 13.jpg', 'Picture 14.jpg', 'Picture 15.jpg','Picture 0.jpg', 'Picture 1.jpg', 'Picture 10.jpg', 'Picture 11.jpg', 'Picture 12.jpg', 'Picture 16.jpg', 'Picture 17.jpg', 'Picture 18.jpg', 'Picture 19.jpg', 'Picture 2.jpg', 'Picture 20.jpg', 'Picture 21.jpg', 'Picture 22.jpg', 'Picture 23.jpg', 'Picture 24.jpg', 'Picture 25.jpg', 'Picture 26.jpg', 'Picture 27.jpg', 'Picture 28.jpg', 'Picture 29.jpg', 'Picture 3.jpg', 'Picture 30.jpg', 'Picture 31.jpg', 'Picture 32.jpg', 'Picture 33.jpg', 'Picture 34.jpg', 'Picture 35.jpg', 'Picture 36.jpg', 'Picture 37.jpg']   
>>> print(natsorted(ll,reverse=True)) 
['Picture 37.jpg', 'Picture 36.jpg', 'Picture 35.jpg', 'Picture 34.jpg', 'Picture 33.jpg', 'Picture 32.jpg', 'Picture 31.jpg', 'Picture 30.jpg', 'Picture 29.jpg', 'Picture 28.jpg', 'Picture 27.jpg', 'Picture 26.jpg', 'Picture 25.jpg', 'Picture 24.jpg', 'Picture 23.jpg', 'Picture 22.jpg', 'Picture 21.jpg', 'Picture 20.jpg', 'Picture 19.jpg', 'Picture 18.jpg', 'Picture 17.jpg', 'Picture 16.jpg', 'Picture 15.jpg', 'Picture 14.jpg', 'Picture 13.jpg', 'Picture 12.jpg', 'Picture 11.jpg', 'Picture 10.jpg', 'Picture 3.jpg', 'Picture 2.jpg', 'Picture 1.jpg', 'Picture 0.jpg'] 
+0

Я получаю ValueError: недействительный литерал для int() с базой 10: – user3474042

+0

Я нашел лучшее решение. Теперь будет обновляться. Но я не получал ошибок в данных. Если у вас есть только номера, имя должно работать для вас. Но поскольку есть общий подход, вам может понравиться это лучше. – LetzerWille

2

I have a directory with jpgs and other files in it.

[...]

['0.jpg', '1.jpg', '10.jpg', '11.jpg', '12.jpg', '13.jpg', '14.jpg', '15.jpg', '16.jpg', '17.jpg', '18.jpg', '19.jpg', '2.jpg', '20.jpg', '21.jpg', '22.jpg', '23.jpg', '24.jpg', '25.jpg', '26.jpg', '27.jpg', '28.jpg', '29.jpg', '3.jpg', '30.jpg', '31.jpg', '32.jpg', '33.jpg', '34.jpg', '35.jpg', '36.jpg', '37.jpg', '4.jpg', '5.jpg', '6.jpg', '7.jpg', '8.jpg', '9.jpg'] Clearly it sorts blindly the most significant number first. I tried using sorted() as you can see hoping that it would fix it but it makes no difference

Вы можете использовать splitext, чтобы получить часть без расширения и преобразовать его в int для сортировки. Если список с именем 'л' и отсортированный список с именем 'lsorted' вы можете использовать: «[. 10 ' 'JPG']

lsorted = sorted(l,key=lambda x: int(os.path.splitext(x)[0])) 

os.path.splitext на '10 .jpg Возвращения' поэтому, принимая значение int() элемента zero, вы захотите, что хотите, если имена файлов без расширения содержат строки, которые могут быть преобразованы в целые числа с помощью int(). В противном случае вы столкнетесь с ошибкой.

+0

Ha! работает! Спасибо за объяснение! – user3474042

+0

Нет проблем. Повеселись. – hft

Смежные вопросы