python - 根据另一个具有不完整值的较短列表对列表进行排序

标签 python list sorting python-3.6

我有一个文件路径列表,在读取和处理文件之前,我需要以特定方式对其进行排序。 特定方式由一个较小的列表定义,该列表仅包含一些文件名称,但不是全部。 presorted_list 中未列出的所有其他文件路径需要保持之前的顺序。

示例:

some_list = ['path/to/bar_foo.csv',
             'path/to/foo_baz.csv',
             'path/to/foo_bar(ignore_this).csv',
             'path/to/foo(ignore_this).csv',
             'other/path/to/foo_baz.csv']

presorted_list = ['foo_baz', 'foo']

expected_list = ['path/to/foo_baz.csv',
                 'other/path/to/foo_baz.csv',
                 'path/to/foo(ignore_this).csv',
                 'path/to/bar_foo.csv',
                 'path/to/foo_bar(ignore_this).csv']

我找到了一些相关帖子:

但据我所知,问题和答案总是依赖于两个长度相同的列表,而我没有(这会导致诸如 ValueError: 'bar_foo' is not in list) 或需要包含我无法提供的所有可能值的预排序列表。

我的想法:

我提出了一个似乎可行的解决方案,但我不确定这是否是解决问题的好方法:

import os
import re

EXCPECTED_LIST = ['path/to/foo_baz.csv',
                  'other/path/to/foo_baz.csv',
                  'path/to/foo(ignore_this).csv',
                  'path/to/bar_foo.csv',
                  'path/to/foo_bar(ignore_this).csv']

PRESORTED_LIST = ["foo_baz", "foo"]


def sort_function(item, len_list):
    # strip path and unwanted parts
    filename = re.sub(r"[\(\[].*?[\)\]]", "", os.path.basename(item)).split('.')[0]

    if filename in PRESORTED_LIST:
        return PRESORTED_LIST.index(filename)
    return len_list


def main():
    some_list = ['path/to/bar_foo.csv',
                 'path/to/foo_baz.csv',
                 'path/to/foo_bar(ignore_this).csv',
                 'path/to/foo(ignore_this).csv',
                 'other/path/to/foo_baz.csv',]
    list_length = len(some_list)
    sorted_list = sorted(some_list, key=lambda x: sort_function(x, list_length))

    assert sorted_list == EXCPECTED_LIST


if __name__ == "__main__":
    main()

还有其他(更短、更Pythonic)的方法来解决这个问题吗?

最佳答案

我想我会这样做:

import re
from collections import OrderedDict
from itertools import chain

some_list = ['path/to/bar_foo.csv',
             'path/to/foo_baz.csv',
             'path/to/foo_bar(ignore_this).csv',
             'path/to/foo(ignore_this).csv',
             'other/path/to/foo_baz.csv']
presorted_list = ['foo_baz', 'foo']
expected_list = ['path/to/foo_baz.csv',
                 'other/path/to/foo_baz.csv',
                 'path/to/foo(ignore_this).csv',
                 'path/to/bar_foo.csv',
                 'path/to/foo_bar(ignore_this).csv']

def my_sort(lst, presorted_list):
    rgx = re.compile(r"^(.*/)?([^/(.]*)(\(.*\))?(\.[^.]*)?$")
    d = OrderedDict((n, []) for n in presorted_list)
    d[None] = []
    for p in some_list:
        m = rgx.match(p)
        n = m.group(2) if m else None
        if n not in d:
            n = None
        d[n].append(p)
    return list(chain.from_iterable(d.values()))

print(my_sort(some_list, presorted_list) == expected_list)
# True

关于python - 根据另一个具有不完整值的较短列表对列表进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49896864/

相关文章:

python - tkinter 的时间选择器

python - 如何安排一对不同的函数以便真正并行运行?

C# First() 和 Find() 之间的区别

java - 快速排序算法显示错误的输出

python - 机器学习中计算机决策的概率?

python - 如何调用self方法并获取flask中的数据?

python - 在列表中查找特定的子列表

python - 将列表索引拆分为新列表 python

c++ - 在 C++ 中对字符串数组进行排序

sql - 排序结果与 mysql 中的内连接和左连接不同