如何按数字而不是字符串对列表排序?

2024-05-19 11:04:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我有这个密码:

import glob, os
outdir = './output/'
nstring = 'testdat_2014-12-31'
nfilelist = sorted(glob.glob((outdir+'/*{}*.nc').format(nstring)))

我从中得到nfilelist

['testdat_2014-12-31-21_H1.nc',
 'testdat_2014-12-31-21_H10.nc',
 'testdat_2014-12-31-21_H11.nc',
 'testdat_2014-12-31-21_H12.nc',
 'testdat_2014-12-31-21_H2.nc',
 'testdat_2014-12-31-21_H3.nc',
 'testdat_2014-12-31-21_H4.nc',
 'testdat_2014-12-31-21_H5.nc',
 'testdat_2014-12-31-21_H6.nc',
 'testdat_2014-12-31-21_H7.nc',
 'testdat_2014-12-31-21_H8.nc',
 'testdat_2014-12-31-21_H9.nc']

最后的H1-H12数字反映了我想要如何排序。但现在,H10-H12被夹在中间。如何从H1-H12排序?你知道吗

正则表达式不是我的强项,我无法前进。你知道吗

我试着分开走了这么远:

nfilelist[0].split('_')[-1].split('.')
['H1', 'nc']

Tags: import密码output排序osh1globsplit
3条回答

您排序的名称具有简单而规则的结构;您可以在不调用regex的情况下生存。将名称的第一部分置于“\u H”之后,然后将其第一部分置于“.”之前,然后将结果转换为整数,从而对名称进行排序:

sorted(nfilelist, 
       key=lambda x: int(x.split("_H")[1].split(".")[0]))
#['testdat_2014-12-31-21_H1.nc', 'testdat_2014-12-31-21_H2.nc', 
# 'testdat_2014-12-31-21_H3.nc', 'testdat_2014-12-31-21_H4.nc', 
# 'testdat_2014-12-31-21_H5.nc', 'testdat_2014-12-31-21_H6.nc', 
# 'testdat_2014-12-31-21_H7.nc', 'testdat_2014-12-31-21_H8.nc', 
# 'testdat_2014-12-31-21_H9.nc', 'testdat_2014-12-31-21_H10.nc', 
# 'testdat_2014-12-31-21_H11.nc', 'testdat_2014-12-31-21_H12.nc']

假设希望它们按int value排序,则可以按以下方式使用regex

import re

nfiles  = ['testdat_2014-12-31-21_H1.nc',
 'testdat_2014-12-31-21_H10.nc',
 'testdat_2014-12-31-21_H11.nc',
 'testdat_2014-12-31-21_H12.nc',
 'testdat_2014-12-31-21_H2.nc',
 'testdat_2014-12-31-21_H3.nc',
 'testdat_2014-12-31-21_H4.nc',
 'testdat_2014-12-31-21_H5.nc',
 'testdat_2014-12-31-21_H6.nc',
 'testdat_2014-12-31-21_H7.nc',
 'testdat_2014-12-31-21_H8.nc',
 'testdat_2014-12-31-21_H9.nc']

result = sorted(nfiles, key=lambda x: int(re.search('H(\d+)\.nc', x).group(1)))

print(result)

输出

['testdat_2014-12-31-21_H1.nc', 'testdat_2014-12-31-21_H2.nc', 'testdat_2014-12-31-21_H3.nc', 'testdat_2014-12-31-21_H4.nc', 'testdat_2014-12-31-21_H5.nc', 'testdat_2014-12-31-21_H6.nc', 'testdat_2014-12-31-21_H7.nc', 'testdat_2014-12-31-21_H8.nc', 'testdat_2014-12-31-21_H9.nc', 'testdat_2014-12-31-21_H10.nc', 'testdat_2014-12-31-21_H11.nc', 'testdat_2014-12-31-21_H12.nc']

解释

模式'H(\d+)\.nc'表示匹配任何一组数字(\d+),前面是H,后面是.nc。并使用.group(1)获得数字组。然后将这些数字组转换成int,并将它们用作排序的键。你知道吗

无正则表达式

如果要完全避免regex,请使用以下函数作为键:

def key(element):
    digits = (ix for ix in element.split('_')[-1] if ix.isdigit())
    return int(''.join(digits))

result = sorted(nfiles, key=key)

print(result)

注意

最后,如果要按字符串值排序,只需删除对int函数的调用。你知道吗

不用正则表达式就可以实现这一点

result = sorted(nfilelist, key=lambda x: (len(x), x))

这个键首先将这些文件名与

  1. 越长的数字越大
  2. 如果数字长度相同,那么比较数字或字符串是相同的

与其他答案的速度比较:

| Method            | Timing                       |
+-------------------+------------------------------+
| Using natsort     | 219 µs  ± 1.13 µs per loop   |
| Daniel's regex    | 14.2 µs ± 434  ns per loop   |
| Daniel's no-regex | 14.2 µs ± 101  ns per loop   |
| DYZ's split based | 7.50 µs ± 240  ns per loop   |
| This answer       | 2.77 µs ± 46.6 ns per loop   |

在2.7 GHz Intel Core i7上运行的iPython3.7中使用%timeit获得计时

相关问题 更多 >

    热门问题