如何用数字而不是字符串对列表进行排序?

时间:2018-10-27 00:11:52

标签: python regex list sorting

我有此代码:

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']

4 个答案:

答案 0 :(得分:3)

假设您希望他们按 int值对其进行排序,则可以按以下方式使用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,并将其用作排序的键。

无正则表达式

如果要完全避免使用正则表达式,请使用以下函数作为键:

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函数的调用即可。

答案 1 :(得分:0)

使用natsort模块中的sorted()代替natsorted()函数:

import natsort        # pip install natsort

nfilelist = natsort.natsorted(glob.glob((outdir+'/*{}*.nc').format(nstring)))

(名称natsort表示自然排序-与词典分类法相对。)

答案 2 :(得分:0)

您排序的名称具有简单且规则的结构;您无需调用正则表达式即可生存。对名称进行排序,方法是将名称的第一部分放在“ _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']

答案 3 :(得分:0)

您无需使用正则表达式即可实现

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获取了时间