基于条件在Python中反转列表

5
我想以一种方式对这个列表进行排序,其中.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之间)? - Blckknght
2个回答

10

使用自定义的key函数和reverse=True参数调用sorted方法:

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'),非常棒的答案。 - Filip Młynarski
谢谢你提供的解决方案。如果我想按升序排序gz文件,例如log.1.gz...log.30.gz,并且还要将.log文件保留在顶部,我们该如何做呢? - user15051990
@user15051990,这是一个简单的更改。只需在int前面添加负号即可使整数按升序排序。get_sort_keys()的最后一行将变为:return (sort_key[0], sort_key[1], -int(sort_key[2].strip(".")) if sort_key[2] else 0) - pault

2
如果有多个扩展名,则将排名分配给字典,以增加灵活性。
最初的回答: Assign rank in dictionary if multiple extensions for increased flexibility.
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)

this will give

['/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) - pault

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接