【问题标题】:Reverse a list in python based on condition根据条件反转python中的列表
【发布时间】:2019-01-29 20:24:51
【问题描述】:

我想以 .log 应该是第一个文件并且 .gz 文件应该按降序排列的方式对这个列表进行排序

my_list = [
     '/abc/a.log.1.gz',
     '/abc/a.log',
     '/abc/a.log.30.gz',
     '/abc/a.log.2.gz',
     '/abc/a.log.5.gz',
     '/abc/a.log.3.gz',
     '/abc/a.log.6.gz',
     '/abc/a.log.4.gz',
     '/abc/a.log.12.gz',
     '/abc/a.log.10.gz',
     '/abc/a.log.8.gz',
     '/abc/a.log.14.gz',
     '/abc/a.log.29.gz'
]

预期结果:

my_list = ['/abc/a.log',
        '/abc/a.log.30.gz',
        '/abc/a.log.29.gz',
        '/abc/a.log.29.gz',
        '/abc/a.log.14.gz',
        '/abc/a.log.12.gz',
        '/abc/a.log.10.gz',
        '/abc/a.log.8.gz',
        '/abc/a.log.6.gz',
        '/abc/a.log.5.gz',
        '/abc/a.log.4.gz',
        '/abc/a.log.3.gz',
        '/abc/a.log.2.gz'
        '/abc/a.log.1.gz']

reversed(mylist) 也没有得到我想要的解决方案。

【问题讨论】:

  • 编号的压缩文件是否仅包含您显示的数字,或者其他数字(如 10)是否混入(在您当前的代码中排序在 1 和 2 之间,但打算介于 2 和30)?

标签: python list sorting


【解决方案1】:

sorted 与自定义key 函数和reverse=True 一起使用:

print(sorted(my_list, key=lambda x: (x.endswith('log'), x), reverse=True))
#['/abc/spa/a.log',
# '/abc/spa/a.log.30.gz',
# '/abc/spa/a.log.2.gz',
# '/abc/spa/a.log.1.gz']

根据更新后的问题,您似乎正在尝试对文件名进行排序。我建议使用os.path 来操作这些字符串。

首先您可以使用os.path.splitext 拆分扩展名来比较.log.gz。然后再去掉扩展名,得到文件号,转换成整数。

例如:

import os

def get_sort_keys(filepath):
    split_file_path = os.path.splitext(filepath)
    sort_key = (split_file_path[1], *os.path.splitext(split_file_path[0]))
    return (sort_key[0], sort_key[1], int(sort_key[2].strip(".")) if sort_key[2] else 0)

print(sorted(my_list, key=get_sort_keys, reverse=True))
#['/abc/a.log',
# '/abc/a.log.30.gz',
# '/abc/a.log.29.gz',
# '/abc/a.log.14.gz',
# '/abc/a.log.12.gz',
# '/abc/a.log.10.gz',
# '/abc/a.log.8.gz',
# '/abc/a.log.6.gz',
# '/abc/a.log.5.gz',
# '/abc/a.log.4.gz',
# '/abc/a.log.3.gz',
# '/abc/a.log.2.gz',
# '/abc/a.log.1.gz']

在这个版本中,我没有像以前那样明确检查 endswith("log"),但我依赖于 log 扩展名将按字典顺序排在 gz 之后的事实。

【讨论】:

  • 很好地使用x.endswith('log'),很好的答案。
  • 感谢您的解决方案。如果我想按 log.1.gz...,log.30.gz 的升序对 gz 进行排序,现在还要将 .log 文件放在顶部。我们怎样才能做到这一点?
  • @user15051990 这是一个简单的更改。只需在 int 前面添加一个负号,以便整数升序排序。 get_sort_keys() 的最后一行将变为:return (sort_key[0], sort_key[1], -int(sort_key[2].strip(".")) if sort_key[2] else 0
【解决方案2】:

如果有多个扩展名,则在字典中分配排名以具有更大的灵活性

my_list = ['/abc/spa/a.log.1.gz',
 '/abc/spa/a.log',
 '/abc/spa/a.log.30.tar',
 '/abc/spa/a.log.30.gz',
 '/abc/spa/a.log.2.gz']

rank={'log':1,'gz':2,'tar':3}    # 'tar' is optional here
sorted(my_list,key = lambda x : (-rank.get(x.rsplit('.')[-1],0), x),reverse=True)

这会给

['/abc/spa/a.log',
 '/abc/spa/a.log.30.gz',
 '/abc/spa/a.log.2.gz',
 '/abc/spa/a.log.1.gz',
 '/abc/spa/a.log.30.tar']

对于您更新的问题

my_list = [
     '/abc/a.log.1.gz',
     '/abc/a.log',
     '/abc/a.log.30.gz',
     '/abc/a.log.2.gz',
     '/abc/a.log.5.gz',
     '/abc/a.log.3.gz',
     '/abc/a.log.6.gz',
     '/abc/a.log.4.gz',
     '/abc/a.log.12.gz',
     '/abc/a.log.10.gz',
     '/abc/a.log.8.gz',
     '/abc/a.log.14.gz',
     '/abc/a.log.29.gz'
]
rank={'log':1,'gz':2,'tar':3}    # 'tar' is optional here
sorted(my_list,key = lambda x : (-rank.get(x.rsplit('.',1)[-1]), int(x.split('.')[-2]) if x.split('.')[-2].isdigit() else 0),reverse=True)

输出:

['/abc/a.log',
 '/abc/a.log.30.gz',
 '/abc/a.log.29.gz',
 '/abc/a.log.14.gz',
 '/abc/a.log.12.gz',
 '/abc/a.log.10.gz',
 '/abc/a.log.8.gz',
 '/abc/a.log.6.gz',
 '/abc/a.log.5.gz',
 '/abc/a.log.4.gz',
 '/abc/a.log.3.gz',
 '/abc/a.log.2.gz',
 '/abc/a.log.1.gz']

【讨论】:

  • 这是有道理的。如果目标是首先按扩展名排序,然后是文件名,我会做类似sorted(my_list, key=lambda x: (x.rsplit(".", 1)[-1], x), reverse=True) 的事情。
猜你喜欢
  • 2021-07-20
  • 2018-08-23
  • 1970-01-01
  • 2019-10-30
  • 1970-01-01
  • 2019-02-02
  • 1970-01-01
  • 2019-06-25
  • 1970-01-01
相关资源
最近更新 更多