首页 > 解决方案 > 根据来自另一个列表/字典的顺序对列表中的文件名进行排序

问题描述

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

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还想根据. 所以会出现在for之前,同样我们将使用. 我还有其他扩展名不同于 p2kernel 的文件,它们的顺序不需要更改。"pkernel"val1val2value_dict"oranges""apples"val1value_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']

我试图使用这些 sorted(s, key = operator.itemgetter(1, 2))方法,但我不知道如何将字典的结果应用到排序子集中。所以我最终使用 sublime text 操作手动完成这个过程。有没有办法自动化这个?

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

标签: pythonsorting

解决方案


你的问题定义不明确,“订单不会改变”,所以我假设不存在的键被排序到开头或结尾。

这是一种选择:

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

推荐阅读