Сортировка имен файлов в списке по порядку из другого списка / словаря - PullRequest
0 голосов
/ 09 июля 2020

У меня есть отсортированный список имен файлов, подобный этому:

files = ['root/base/val1/apples/pkernel', 
         'root/base/val1/oranges/pkernel',  
         'root/base/val1/eng_scope_lattice/p2_kernel',
         'root/base/val2/grapes/pkernel',
         'root/base/val2/exact_scope_lattice/p2_kernel',
         'root/base/val2/peaches/pkernel',
         'root/base/val2/pineapple/pkernel']

и у меня есть словарь value_dict:

value_dict = {'val1':[oranges,apples], 'val2':[peaches, grapes, pineapples]}

Я отсортировал список files, но Я также хочу отсортировать файлы, которые заканчиваются на "pkernel" внутри каждого значения (val1 и val2 в данном случае), в зависимости от порядка в value_dict. Таким образом, "oranges" будет предшествовать "apples" вместо val1, и аналогично мы будем использовать порядок, указанный в value_dict. У меня также есть другие файлы с расширениями, отличными от p2kernel, порядок которых не нужно менять.

Так что мой final_list будет

final_list = ['root/base/val1/oranges/pkernel', 
              'root/base/val1/apples/pkernel',  
              'root/base/val1/eng_scope_lattice/p2_kernel',
              'root/base/val2/peaches/pkernel',
              'root/base/val2/exact_scope_lattice/p2_kernel',
              'root/base/val2/grapes/pkernel',
              'root/base/val2/pineapple/pkernel']

Я пытался использовать sorted(s, key = operator.itemgetter(1, 2)) методов, но я не знаю, как применять результаты словаря в подмножествах сортировки. В итоге я выполняю этот процесс вручную, используя возвышенные текстовые операции. Есть ли способ автоматизировать это?

Для расширений файлов, отличных от p1kernel, порядок в исходном списке должен оставаться неизменным.

Ответы [ 3 ]

0 голосов
/ 09 июля 2020

Да, это больше, чем способ автоматизировать. Я объясню вам один очень простой алгоритм, возможно, не самый быстрый, но он лучше, чем использование возвышенных текстовых операций.

  1. Преобразуйте ваш массив файлов в массив массивов, я имею в виду использование split ("/" ) для каждой строки, чтобы преобразовать их в список.
  2. Вы можете использовать sorted (new_list, key = lambda path_file_list: customKeyFunction (path_file_list))

Где

def customKeyFunction(path_file):
  val_path = path_file[2]
  try:
    key = value_dict[val_path].index(path_file[3])
  except ValueError:
    key = -1
  return key


sorted(new_list, key=lambda path_file_list: customKeyFunction(path_file_list))

Отказ от ответственности: это изменит порядок файлов p2kernel. Но с этим вам есть с чего начать.

0 голосов
/ 09 июля 2020

Ваш вопрос неверно определен с "порядок не будет изменен", поэтому я предполагаю, что отсутствующие ключи отсортированы в начало или конец.

Вот один из вариантов:

>>> sorted(files, key=sort_order)
['root/base/val1/eng_scope_lattice/p2_kernel',
 'root/base/val1/oranges/pkernel',
 'root/base/val1/apples/pkernel',
 'root/base/val2/exact_scope_lattice/p2_kernel',
 'root/base/val2/pineapple/pkernel',
 'root/base/val2/peaches/pkernel',
 'root/base/val2/grapes/pkernel']

где мы определяем sort_order следующим образом:

import math

files = [
    'root/base/val1/apples/pkernel',
    'root/base/val1/oranges/pkernel',  
    'root/base/val1/eng_scope_lattice/p2_kernel',  
    'root/base/val2/grapes/pkernel', 
    'root/base/val2/exact_scope_lattice/p2_kernel',
    'root/base/val2/peaches/pkernel',
    'root/base/val2/pineapple/pkernel'
]
_orders = {
    'val1': ['oranges', 'apples'],
    'val2': ['peaches', 'grapes', 'pineapples']
}
orders = {k: {val: ind for ind, val in enumerate(v)} for k, v in _orders.items()}
digits = {k: int(math.ceil(math.log(len(v), 10))) for k, v in orders.items()}

BASE = ['root', 'base']

def sort_order(file):
    fragments = file.split('/')
    if fragments[:2] == BASE:
        if len(fragments) > 3:
            folder, subfolder = fragments[2:4]
            if folder in orders:
                index = orders[folder].get(subfolder, '')  # Put unknown first
                str_index = index and f'{index:0{digits[folder]}d}'
            fragments[3] = f'{str_index}/{subfolder}'
    return fragments

Нам приходится делать глупые вещи, потому что python3 не позволяет вставлять, например, (1, 'foo') в середине списка строк. и сравнивая их, в виде

[['root', 'base', 'val1', '1/apples', 'pkernel'],
 ['root', 'base', 'val1', '0/oranges', 'pkernel'],
 ['root', 'base', 'val1', '/eng_scope_lattice', 'p2_kernel'],
 ['root', 'base', 'val2', '1/grapes', 'pkernel'],
 ['root', 'base', 'val2', '/exact_scope_lattice', 'p2_kernel'],
 ['root', 'base', 'val2', '0/peaches', 'pkernel'],
 ['root', 'base', 'val2', '/pineapple', 'pkernel']]
0 голосов
/ 09 июля 2020

Мне очень непонятно, какие именно правила вы собираетесь применить к сортировке. Кроме того, этот способ работы довольно хакерский и делает много предположений о том, как могут выглядеть ваши входные данные. При этом это почти делает то, что вы просите, за исключением того, что в вашем примере вы помещаете элементы из списков перед другими элементами для папки val 1, но не папки val2. В любом случае, я думаю, что вы сможете заставить все работать на основе этого кода. Отредактировано: исправлена ​​ошибка копирования и вставки в коде.

def getKey(val): 
    for k,v in value_dict.items: 
        if val.find(k) != -1: 
            for i in range(len(v)): 
                val = val.replace(v[i],str(i)) 
    return val

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