根据另一个列表/字典中的顺序对列表中的文件名进行排序

时间:2020-07-09 00:17:17

标签: python sorting

我有一个这样的文件名排序列表:

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"的{​​{1}}之前,并且类似地,我们将使用val1中指定的顺序。我还有其他扩展名不同于p2kernel的文件,其顺序无需更改。

所以我的value_dict

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'] 方法,但是我不知道如何将字典的结果应用于排序子集。因此,我最终使用崇高的文本操作手动完成了此过程。有没有办法使它自动化?

对于p1kernel以外的文件扩展名,原始列表中的顺序应保持不变。

3 个答案:

答案 0 :(得分:0)

我不清楚您打算对排序应用什么规则。同样,这种处理方式很容易出错,并且对允许输入的内容进行了很多假设。话虽如此,这几乎可以满足您的要求,只是在示例中,您将列表中的项目放在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)

答案 1 :(得分:0)

是的,有多种方法可以实现此自动化。 我将向您介绍一种非常简单的算法,也许不是最快的算法,但是比使用崇高的文本操作更好。

  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文件的顺序。但是与此相关的是您要开始的事情。

答案 2 :(得分:0)

您的问题定义不明确,“顺序不会更改”,因此我假设不存在的键排在开头或结尾。

这里是一种选择:

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