Как отсортировать файлы в порядке возрастания целого числа, содержащегося в имени файла - PullRequest
1 голос
/ 12 марта 2019

У меня есть список a. Я хочу расположить эти файлы в порядке возрастания, например,

  1. kernal_1.0.npy
  2. kernal_10.npy
  3. kernal_50.npy
  4. kernal_100.npy

Если я использую функцию разбиения, она разбивает только расширение npy Сортированная функция отлично работает только на целых числах. Что я должен сделать для этого?

a = ['kernal_1.0.npy','kernal_100.npy','kernal_50.npy','kernal_10.npy' ]
b='kernal_1.0.npy'
print(os.path.splitext(b))

Ответы [ 5 ]

2 голосов
/ 12 марта 2019

Поскольку начало всегда одно и то же, как и конец, вы можете выполнить поиск на основе индекса.

a = ['kernal_1.0.npy','kernal_100.npy','kernal_50.npy','kernal_10.npy' ]
prefix_len = len('kernal_')
prefix_ext = len('.npy')

# Here, the key parameter means *how* you want to sort your list. So, 
# basically, at each operation, it will sort based on this argument. The 
# lambda here is basically a function, on which I invite you to document 
# yourself on.
# This line says : Sort this list, and compare every elements using 
# only the letters between the prefix_len'th index and the prefix_ext index,
# casted as `float` numbers.
b = sorted(a, key = lambda x: float(x[prefix_len:-prefix_ext]) )

print(b)
# ['kernal_1.0.npy', 'kernal_10.npy', 'kernal_50.npy', 'kernal_100.npy']

Возможно, более подробное объяснение для вас.

def show_list_based_on_lambda(arr, key):
    """ When you use the key parameter in a sorting function, it behaves
        the same way as here. Meaning at every iteration, it will
        only consider the elements returned by the function you sent in.
    """
    for elem in arr:
        print( key(elem) )


#   This function is supposed to strip off the first and last character of an iterable.
f = lambda x:x[1:-1]
arr = ['aaa', 'bbb', 'ccc', 'ddd', 'eee']
show_list_based_on_lambda(arr, f)
# a
# b
# c
# d
# e


#   This function is supposed to add one to every element that passes by.
f = lambda x:x+1
arr = [10, 20, 30, 40, 50]
show_list_based_on_lambda(arr, f)
# 11
# 21
# 31
# 41
# 51
0 голосов
/ 12 марта 2019

Попробуйте это:

b = sorted(a, key = lambda x : int(x[x.find('_')+1:].split('.')[0]))

ВЫХОД :

b = ['kernal_1.0.npy', 'kernal_10.npy', 'kernal_50.npy', 'kernal_100.npy']
0 голосов
/ 12 марта 2019

Вы можете попробовать следующий старый и классический способ:

import re

def numeric_compare(x, y):
  u = re.findall("\d+(?:\.\d+)?", x)
  v = re.findall("\d+(?:\.\d+)?", y)
  u = [0] if len(u) == 0 else u
  v = [0] if len(v) == 0 else v
  return int(float(u[0]) - float(v[0]))

a = ['kernal_1.0.npy','kernal_100.npy','kernal_50.npy','kernal_10.npy' ]
print(a)
print(sorted(a, cmp=numeric_compare))

Вывод:

['kernal_1.0.npy', 'kernal_100.npy', 'kernal_50.npy', 'kernal_10.npy']
['kernal_1.0.npy', 'kernal_10.npy', 'kernal_50.npy', 'kernal_100.npy']

Пояснения:

  • Вы определяете свою собственную функцию сортировки numeric_compare
  • Вы извлекаете действительные числа из сравниваемой строки
  • Если ваша строка не содержит заданного вами числазначение 0
  • Затем вы сравниваете оба извлеченных числа с плавающей точкой и приводите их обратно к int, так как вам нужно, чтобы ваша функция возвращала int
  • Вы вызываете sorted()в вашем списке с функцией сравнения

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

input:

b = ['kernal_1.0.npy','kernal_100.npy','kernal_50.npy','kernal_10.npy', 'abc' ]

вывод:

['abc', 'kernal_1.0.npy', 'kernal_10.npy', 'kernal_50.npy', 'kernal_100.npy']

Если вы предпочитаете, чтобы файлы, в которых не было номеров, появлялись в конце списка вместоПосле сортировки в начале вы можете заменить u = [0] и v = [0] на u = [sys.maxsize] и v = [sys.maxsize].(вам нужно добавить import sys в начале вашего кода)

Демонстрация Regex и пояснения :
https://regex101.com/r/evIeVD/1/

0 голосов
/ 12 марта 2019

Используйте os.path.splitext с str.split в sorted или list.sort:

import os

a = ['kernal_1.0.npy','kernal_100.npy','kernal_50.npy','kernal_10.npy']

sorted(a, key = lambda x: float(os.path.splitext(x)[0].split('_')[1]))
# ['kernal_1.0.npy', 'kernal_10.npy', 'kernal_50.npy', 'kernal_100.npy']
0 голосов
/ 12 марта 2019

Вы можете использовать Pandas Series для обобщения решения:

a = np.array(['kernal_1.0.npy','kernal_100.npy','kernal_50.npy','kernal_10.npy' ])
idx_ = pd.Series(a).str.split('.', expand=True).iloc[:, 0]\
        .str.split('_', expand=True).iloc[:, 1]\
        .astype(int).sort_values(0).index

a[idx_]
array(['kernal_1.0.npy', 'kernal_10.npy', 'kernal_50.npy',
       'kernal_100.npy'], dtype='<U14')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...