无论出于何种原因,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 Explorer 将排序 !1, 1, !a, a。
因此,如果您想像 Windows Explorer 在 Python 中一样进行排序,您必须通过 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)
从 7.1.0 版开始,natsort 支持 os_sorted,它在内部使用前面提到的 Windows API 或 Linux 排序,应该使用而不是 natsorted()。