Как отсортировать список по числам, а не по строке?

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

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

См. stackoverflow.com/questions/5967500/…

Vatsal 27.10.2018 02:17

@maximusdooku вы хотите отсортировать по значению int или строковому значению?

Dani Mesejo 27.10.2018 02:24
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
67
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Предполагая, что вы хотите, чтобы они отсортировали их по значение 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;)

lakshayg 27.10.2018 06:29

@LakshayGarg Согласно OP, это невозможно: nstring = 'testdat_2014-12-31'.

DYZ 27.10.2018 06:56

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

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 с тактовой частотой 2,7 ГГц.

Другие вопросы по теме