我有一个排序的文件名列表,如下所示:
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
中的顺序对每个值(在本例中为val1
和val2
(内以"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)
是的,有很多方法可以实现自动化。我将向您解释一个非常简单的算法,可能不是最快的,但它比使用出色的文本操作要好。
- 将文件数组转换为数组,我的意思是对每个字符串使用split("/"(,以便在列表中转换它们
- 可以使用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']]