Как я могу отсортировать список по номерам вместо строки? - PullRequest
0 голосов
/ 27 октября 2018

У меня есть этот код:

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?

Regex не моя сильная сторона, и я не могу двигаться вперед.

Я попытался разделиться и получил это далеко:

nfilelist[0].split('_')[-1].split('.')
['H1', 'nc']

Ответы [ 4 ]

0 голосов
/ 27 октября 2018

Вы можете достичь этого без использования регулярных выражений

result = sorted(nfilelist, key=lambda x: (len(x), x))

Этот ключ сначала сравнивает эти имена файлов с идеей, что

  1. Чем больше число, тем больше
  2. Если числа одинаковой длины, то сравнение чисел или строк одинаково

Сравнение скорости с другими ответами здесь:

| 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 * 1016 с частотой 2,7 ГГц *

0 голосов
/ 27 октября 2018

Вместо функции sorted() используйте natsorted() из модуля natsort :

import natsort        # pip install natsort

nfilelist = natsort.natsorted(glob.glob((outdir+'/*{}*.nc').format(nstring)))

(имя natsort означает естественная сортировка - в отличие от лексикографического один.)

0 голосов
/ 27 октября 2018

Имена, которые вы сортируете, имеют простую и правильную структуру; Вы можете выжить без использования регулярных выражений. Сортируйте имена, взяв первую часть имени после «_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']
0 голосов
/ 27 октября 2018

Если вы хотите, чтобы они сортировали их по int значению , вы можете использовать regex следующим образом:

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...