不管出于什么原因,Python都没有内置的方法来进行自然排序(意味着1、2、10而不是1、10、2),因此您必须自己编写:
import re
def sorted_alphanumeric(data):
convert = lambda text: int(text) if text.isdigit() else text.lower()
alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ]
return sorted(data, key=alphanum_key)
现在,您可以使用此功能对列表进行排序:
dirlist = sorted_alphanumeric(os.listdir(...))
问题:
如果您使用上述函数对字符串(例如文件夹名称)进行排序,并希望像Windows资源管理器一样对它们进行排序,则在某些情况下无法正常使用。
如果您的文件夹名称中带有某些“特殊”字符,则此排序功能将在Windows上返回不正确的结果。例如,此函数将排序1, !1, !a, a
,而Windows资源管理器将排序!1, 1, !a, a
。
因此,如果您想像Python中的Windows资源管理器那样进行排序,则必须通过ctypes 使用Windows内置函数StrCmpLogicalW(这当然在Unix上不起作用):
from ctypes import wintypes, windll
from functools import cmp_to_key
def winsort(data):
_StrCmpLogicalW = windll.Shlwapi.StrCmpLogicalW
_StrCmpLogicalW.argtypes = [wintypes.LPWSTR, wintypes.LPWSTR]
_StrCmpLogicalW.restype = wintypes.INT
cmp_fnc = lambda psz1, psz2: _StrCmpLogicalW(psz1, psz2)
return sorted(data, key=cmp_to_key(cmp_fnc))
此功能比稍慢sorted_alphanumeric()
。
奖励:winsort
还可以在Windows上对完整路径进行排序。
另外,尤其是在使用Unix的情况下,可以使用natsort
库(pip install natsort
)以正确的方式对完整路径进行排序(意味着子文件夹位于正确的位置)。
您可以像这样使用它来排序完整路径:
from natsort import natsorted, ns
dirlist = natsorted(dirlist, alg=ns.PATH | ns.IGNORECASE)
不要将其用于仅对文件夹名称(或通常为字符串)进行常规排序,因为它比sorted_alphanumeric()
上面的函数要慢很多。如果您期望Windows资源管理器排序,该
natsorted
库将给您不正确的结果,因此可以使用winsort()
它。