如何在Python中以非常特定的方式对列表进行排序?

时间:2018-09-11 21:45:23

标签: python

如何在Python中对列表进行非常明确的排序?我的意思是,应该以非常特定的方式对项目进行排序,而不仅仅是字母或数字。我将收到的输入看起来如下所示:

h43948fh4349f84 ./.file.html
dsfj940j90f94jf ./abcd.ppt
f9j3049fj349f0j ./abcd_FF_000000001.jpg
f0f9049jf043930 ./abcd_FF_000000002.jpg
j909jdsa094jf49 ./abcd_FF_000000003.jpg
jf4398fj9348fjj ./abcd_FFinit.jpg
9834jf9483fj43f ./abcd_MM_000000001.jpg
fj09jw93fj930fj ./abcd_MM_000000002.jpg
fjdsjfd89s8hs9h ./abcd_MM_000000003.jpg
vyr89r8y898r839 ./abcd_MMinit.jpg

列表应排序:

  1. html文件优先
  2. 第二个ppt文件
  3. FFinit文件第三
  4. MMinit文件第四个
  5. 其余编号文件按FF / MM顺序

示例输出如下:

h43948fh4349f84 ./.file.html
dsfj940j90f94jf ./abcd.ppt
jf4398fj9348fjj ./abcd_FFinit.jpg
vyr89r8y898r839 ./abcd_MMinit.jpg
f9j3049fj349f0j ./abcd_FF_000000001.jpg
9834jf9483fj43f ./abcd_MM_000000001.jpg
f0f9049jf043930 ./abcd_FF_000000002.jpg
fj09jw93fj930fj ./abcd_MM_000000002.jpg
j909jdsa094jf49 ./abcd_FF_000000003.jpg
fjdsjfd89s8hs9h ./abcd_MM_000000003.jpg

3 个答案:

答案 0 :(得分:4)

您需要定义一个key函数,以指导排序。比较值以查看行进方向时,将使用键函数的结果而不是直接使用值。

key函数可以返回任何内容,但是在这里元组会有所帮助。对元组进行“字典式”比较,这意味着仅比较它们的第一个元素,除非它们相等,然后再使用第二个元素。如果它们也相等,则将比较其他元素,直到没有更多元素或确定顺序为止。

对于您的情况,您可以在第一个位置生成一个数字,以对“特殊”条目进行排序,然后在其余位置返回第二个位置的数字和FFMM字符串在最后:

def key(filename):
    if filename.endswith('.html'):
        return (0,)  # html first
    if filename.endswith('.ppt'):
        return (1,)  # ppt second
    if filename.endswith('FFinit.jpg'):
        return (2,)  # FFinit third
    if filename.endswith('MMinit.jpg'):
        return (3,)  # MMinit forth
    # take last two parts between _ characters, ignoring the extension
    _, FFMM, number = filename.rpartition('.')[0].rsplit('_', 2)
    # rest is sorted on the number (compared here lexicographically) and FF/MM
    return (4, number, FFMM)

请注意,元组的长度不必相等。

这将产生预期的输出:

>>> from pprint import pprint
>>> lines = '''\
... h43948fh4349f84 ./.file.html
... dsfj940j90f94jf ./abcd.ppt
... f9j3049fj349f0j ./abcd_FF_000000001.jpg
... f0f9049jf043930 ./abcd_FF_000000002.jpg
... j909jdsa094jf49 ./abcd_FF_000000003.jpg
... jf4398fj9348fjj ./abcd_FFinit.jpg
... 9834jf9483fj43f ./abcd_MM_000000001.jpg
... fj09jw93fj930fj ./abcd_MM_000000002.jpg
... fjdsjfd89s8hs9h ./abcd_MM_000000003.jpg
... vyr89r8y898r839 ./abcd_MMinit.jpg
... '''.splitlines()
>>> pprint(sorted(lines, key=key))
['h43948fh4349f84 ./.file.html',
 'dsfj940j90f94jf ./abcd.ppt',
 'jf4398fj9348fjj ./abcd_FFinit.jpg',
 'vyr89r8y898r839 ./abcd_MMinit.jpg',
 'f9j3049fj349f0j ./abcd_FF_000000001.jpg',
 '9834jf9483fj43f ./abcd_MM_000000001.jpg',
 'f0f9049jf043930 ./abcd_FF_000000002.jpg',
 'fj09jw93fj930fj ./abcd_MM_000000002.jpg',
 'j909jdsa094jf49 ./abcd_FF_000000003.jpg',
 'fjdsjfd89s8hs9h ./abcd_MM_000000003.jpg']

答案 1 :(得分:1)

您可以对key使用sort()参数。 list类的此方法接受列表的元素,并返回一个可以与其他返回值进行比较以确定排序顺序的值。一种可能性是完全按照您在问题中所描述的为每个条件分配一个数字。

答案 2 :(得分:0)

我认为最后一个排序点只是看了文件扩展名前的数字(例如000001)

def custom_key(x):
    substring_order = ['.html','.ppt','FFinit','MMinit']
    other_order = lambda x: int(x.split('_')[-1].split('.')[0])+len(substring_order)
    for i,o in enumerate(substring_order):
        if o in x:
            return i
    return other_order(x)

sorted_list = sorted(data,key=custom_key)

import pprint
pprint.pprint(sorted_list)

Out:
['h43948fh4349f84 ./.file.html',
'dsfj940j90f94jf ./abcd.ppt',
'jf4398fj9348fjj ./abcd_FFinit.jpg',
'vyr89r8y898r839 ./abcd_MMinit.jpg',
'f9j3049fj349f0j ./abcd_FF_000000001.jpg',
'9834jf9483fj43f ./abcd_MM_000000001.jpg',
'f0f9049jf043930 ./abcd_FF_000000002.jpg',
'fj09jw93fj930fj ./abcd_MM_000000002.jpg',
'j909jdsa094jf49 ./abcd_FF_000000003.jpg',
'fjdsjfd89s8hs9h ./abcd_MM_000000003.jpg']