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



我有一个排序的文件名列表,如下所示:

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进行了排序,但我也想根据value_dict中的顺序对每个值(在本例中为val1val2(内以"pkernel"结尾的文件进行排序。因此,对于val1"oranges"将位于"apples"之前,类似地,我们将使用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以外的文件扩展名,原始列表中的顺序应保持不变。

我不清楚您打算将哪些规则应用于排序。此外,这种做事方式很有技巧,并且对你的输入进行了很多假设。话虽如此,这几乎满足了你的要求,除了在你的例子中,你把列表中的项目放在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. 将文件数组转换为数组,我的意思是对每个字符串使用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文件的顺序。但有了这个,你就有了起点。

您的问题用"顺序将不会改变";,所以我将假设不存在的键被排序到开始或结束。

这里有一个选项:

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

最新更新