У меня есть такой код:
import glob, os
outdir = './output/'
nstring = 'testdat_2014-12-31'
nfilelist = sorted(glob.glob((outdir+'/*{}*.nc').format(nstring)))
из которого я получаю nfilelist
:
['testdat_2014-12-31-21_H1.nc',
'testdat_2014-12-31-21_H10.nc',
'testdat_2014-12-31-21_H11.nc',
'testdat_2014-12-31-21_H12.nc',
'testdat_2014-12-31-21_H2.nc',
'testdat_2014-12-31-21_H3.nc',
'testdat_2014-12-31-21_H4.nc',
'testdat_2014-12-31-21_H5.nc',
'testdat_2014-12-31-21_H6.nc',
'testdat_2014-12-31-21_H7.nc',
'testdat_2014-12-31-21_H8.nc',
'testdat_2014-12-31-21_H9.nc']
Числа H1-H12 в конце отражают то, как я хочу его отсортировать. Но прямо сейчас H10-H12 зажат посередине. Как я могу отсортировать от H1 до H12?
Регулярное выражение - не моя сильная сторона, и я не могу двигаться дальше.
Я попробовал разделить и дошел до этого:
nfilelist[0].split('_')[-1].split('.')
['H1', 'nc']
@maximusdooku вы хотите отсортировать по значению int или строковому значению?
Предполагая, что вы хотите, чтобы они отсортировали их по значение int, вы можете использовать регулярное выражение следующим образом:
import re
nfiles = ['testdat_2014-12-31-21_H1.nc',
'testdat_2014-12-31-21_H10.nc',
'testdat_2014-12-31-21_H11.nc',
'testdat_2014-12-31-21_H12.nc',
'testdat_2014-12-31-21_H2.nc',
'testdat_2014-12-31-21_H3.nc',
'testdat_2014-12-31-21_H4.nc',
'testdat_2014-12-31-21_H5.nc',
'testdat_2014-12-31-21_H6.nc',
'testdat_2014-12-31-21_H7.nc',
'testdat_2014-12-31-21_H8.nc',
'testdat_2014-12-31-21_H9.nc']
result = sorted(nfiles, key=lambda x: int(re.search('H(\d+)\.nc', x).group(1)))
print(result)
Выход
['testdat_2014-12-31-21_H1.nc', 'testdat_2014-12-31-21_H2.nc', 'testdat_2014-12-31-21_H3.nc', 'testdat_2014-12-31-21_H4.nc', 'testdat_2014-12-31-21_H5.nc', 'testdat_2014-12-31-21_H6.nc', 'testdat_2014-12-31-21_H7.nc', 'testdat_2014-12-31-21_H8.nc', 'testdat_2014-12-31-21_H9.nc', 'testdat_2014-12-31-21_H10.nc', 'testdat_2014-12-31-21_H11.nc', 'testdat_2014-12-31-21_H12.nc']
Объяснение
Шаблон 'H(\d+)\.nc'
означает соответствие любой группе цифр (\d+)
, перед которой идет H
и за которой следует .nc
. и используйте .group(1)
, чтобы получить группу цифр. Затем преобразуйте группы цифр в int
и используйте их в качестве ключа для сортировки.
Нет регулярного выражения
Если вы хотите полностью избежать регулярного выражения, используйте в качестве ключа следующую функцию:
def key(element):
digits = (ix for ix in element.split('_')[-1] if ix.isdigit())
return int(''.join(digits))
result = sorted(nfiles, key=key)
print(result)
Примечание
Наконец, если вы хотите отсортировать по строковому значению, просто удалите вызовы функции int.
Вместо функции sorted()
используйте функцию natsorted()
из модуля нацорт:
import natsort # pip install natsort
nfilelist = natsort.natsorted(glob.glob((outdir+'/*{}*.nc').format(nstring)))
(Имя natsort
означает естественный сорт - в отличие от лексикографический.)
Имена, которые вы сортируете, имеют простую и правильную структуру; вы можете выжить, не вызывая регулярное выражение. Отсортируйте имена, взяв первую часть имени после «_H», затем первую часть имени перед «.» И преобразовав результат в целое число:
sorted(nfilelist,
key=lambda x: int(x.split("_H")[1].split(".")[0]))
#['testdat_2014-12-31-21_H1.nc', 'testdat_2014-12-31-21_H2.nc',
# 'testdat_2014-12-31-21_H3.nc', 'testdat_2014-12-31-21_H4.nc',
# 'testdat_2014-12-31-21_H5.nc', 'testdat_2014-12-31-21_H6.nc',
# 'testdat_2014-12-31-21_H7.nc', 'testdat_2014-12-31-21_H8.nc',
# 'testdat_2014-12-31-21_H9.nc', 'testdat_2014-12-31-21_H10.nc',
# 'testdat_2014-12-31-21_H11.nc', 'testdat_2014-12-31-21_H12.nc']
Это решение не сработает, если у вас есть файл с именем testdat_2018-12-31-21_H0.nc;)
@LakshayGarg Согласно OP, это невозможно: nstring = 'testdat_2014-12-31'
.
Вы можете добиться этого без использования регулярного выражения
result = sorted(nfilelist, key=lambda x: (len(x), x))
Этот ключ сначала сравнивает эти имена файлов с идеей, что
Сравнение скорости с другими ответами здесь:
| Method | Timing |
+-------------------+------------------------------+
| Using natsort | 219 µs ± 1.13 µs per loop |
| Daniel's regex | 14.2 µs ± 434 ns per loop |
| Daniel's no-regex | 14.2 µs ± 101 ns per loop |
| DYZ's split based | 7.50 µs ± 240 ns per loop |
| This answer | 2.77 µs ± 46.6 ns per loop |
Тайминги были получены с использованием %timeit
в iPython3.7, работающем на Intel Core i7 с тактовой частотой 2,7 ГГц.
См. stackoverflow.com/questions/5967500/…