Python vì bất kỳ lý do gì không đi kèm với một cách tích hợp để sắp xếp tự nhiên (nghĩa là 1, 2, 10 thay vì 1, 10, 2), vì vậy bạn phải tự viết nó:
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)
Bây giờ bạn có thể sử dụng chức năng này để sắp xếp danh sách:
dirlist = sorted_alphanumeric(os.listdir(...))
VẤN ĐỀ:
Trong trường hợp bạn sử dụng hàm trên để sắp xếp các chuỗi (ví dụ: tên thư mục) và muốn chúng được sắp xếp giống như Windows Explorer, nó sẽ không hoạt động bình thường trong một số trường hợp cạnh.
Chức năng sắp xếp này sẽ trả về kết quả không chính xác trên Windows, nếu bạn có tên thư mục với các ký tự 'đặc biệt' nhất định trong đó. Ví dụ, hàm này sẽ sắp xếp 1, !1, !a, a
, trong khi Windows Explorer sẽ sắp xếp !1, 1, !a, a
.
Vì vậy, nếu bạn muốn sắp xếp chính xác như Windows Explorer làm trong Python, bạn phải sử dụng hàm tích hợp sẵn của Windows StrCmpLogicalW thông qua ctypes (điều này tất nhiên sẽ không hoạt động trên 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))
Chức năng này hơi chậm hơn sorted_alphanumeric()
.
Phần thưởng: winsort
cũng có thể sắp xếp các đường dẫn đầy đủ trên Windows .
Ngoài ra, đặc biệt nếu bạn sử dụng Unix, bạn có thể sử dụng natsort
thư viện ( pip install natsort
) để sắp xếp theo các đường dẫn đầy đủ theo cách chính xác (nghĩa là các thư mục con ở đúng vị trí).
Bạn có thể sử dụng nó như thế này để sắp xếp các đường dẫn đầy đủ:
from natsort import natsorted, ns
dirlist = natsorted(dirlist, alg=ns.PATH | ns.IGNORECASE)
Không sử dụng nó để phân loại thông thường chỉ tên thư mục (hoặc chuỗi nói chung), vì nó chậm hơn một chút so với sorted_alphanumeric()
chức năng ở trên.
natsorted
thư viện sẽ cung cấp cho bạn kết quả không chính xác nếu bạn muốn Windows Explorer sắp xếp, vì vậy hãy sử dụng winsort()
cho điều đó.