phân loại danh sách không phân biệt chữ hoa chữ thường, mà không hạ thấp kết quả?


133

Tôi có một danh sách các chuỗi như thế này:

['Aden', 'abel']

Tôi muốn sắp xếp các mục, không phân biệt chữ hoa chữ thường. Vì vậy, tôi muốn nhận được:

['abel', 'Aden']

Nhưng tôi nhận được ngược lại với sorted()hoặc list.sort(), bởi vì chữ hoa xuất hiện trước chữ thường.

Làm thế nào tôi có thể bỏ qua trường hợp? Tôi đã thấy các giải pháp liên quan đến việc hạ thấp tất cả các mục trong danh sách, nhưng tôi không muốn thay đổi trường hợp của các mục trong danh sách.


Hướng dẫn này rất hữu ích: docs.python.org/3/howto/sorting.html#sortinghowto
ady

Câu trả lời:


192

Trong Python 3.3+, có một str.casefoldphương thức được thiết kế riêng cho kết hợp ngẫu nhiên:

sorted_list = sorted(unsorted_list, key=str.casefold)

Trong Python 2 sử dụng lower():

sorted_list = sorted(unsorted_list, key=lambda s: s.lower())

Nó hoạt động cho cả chuỗi bình thường và chuỗi unicode, vì cả hai đều có một lowerphương thức.

Trong Python 2, nó hoạt động để kết hợp các chuỗi bình thường và chuỗi unicode, vì các giá trị của hai loại có thể được so sánh với nhau. Mặc dù vậy, Python 3 không hoạt động như vậy: bạn không thể so sánh chuỗi byte và chuỗi unicode, vì vậy, trong Python 3, bạn nên thực hiện điều lành mạnh và chỉ sắp xếp danh sách một loại chuỗi.

>>> lst = ['Aden', u'abe1']
>>> sorted(lst)
['Aden', u'abe1']
>>> sorted(lst, key=lambda s: s.lower())
[u'abe1', 'Aden']

11
Người ta có thể tránh hàm lambda làm tròn bằng (Python 3) bằng cách sử dụng str.lowerhàm chung là sorted(lst, key=str.lower)hoặc (Python 2) bằng cách sử dụng lowerphương thức của stringmô-đun như sorted(lst, key=string.lower). Người ta cũng có thể sử dụng str.lowercho các chuỗi trong Python 2, nhưng sau đó sẽ phải sử dụng unicode.lowercho unicodecác đối tượng, trong khi string.lowerchấp nhận cả hai (như bạn nói, có lẽ nó không thực sự là một chế độ hoạt động "lành mạnh").
Daniel Andersson

Điều này sẽ không hoạt động cho một danh sách như ['Z', 'B', 'a', 'b', 'A'], sắp xếp theo ['a', 'A', 'B', 'b', 'Z']. Viết hoa 'B' xuất hiện trước chữ thường 'b' vì Python 'sort () và sort () giữ nguyên thứ tự ban đầu khi các chuỗi khớp. Trong trường hợp này, chữ 'B' được coi là khớp với chữ thường 'b' khi sử dụng casefold. Điều này luôn xảy ra nếu bạn chuyển đổi trường hợp để so sánh: được sắp xếp (spam, key = str.lower) hoặc được sắp xếp (spam, key = str.upper) hoặc được sắp xếp (spam, key = str.casefold).
PJ Singh

Thay vào đó, hãy thử giải pháp này: stackoverflow.com/a/1098160/10668287 . Nó sẽ sắp xếp chính xác ['Aden', 'aden'] thành ['aden', 'Aden'].
PJ Singh

46
>>> x = ['Aden', 'abel']
>>> sorted(x, key=str.lower) # Or unicode.lower if all items are unicode
['abel', 'Aden']

Trong Python 3 strlà unicode nhưng trong Python 2, bạn có thể sử dụng phương pháp tổng quát hơn này hoạt động cho cả hai strunicode:

>>> sorted(x, key=lambda s: s.lower())
['abel', 'Aden']

Cảm ơn bạn. Tôi biết tôi nên đã đề cập đến điều này trước đây, nhưng tôi đã nghe nói có vấn đề với việc sử dụng phương pháp này trên chuỗi unicode (Py2). Bạn có biết gì về điều đó?

Chúng đều là unicode. Cảm ơn! Thêm một câu hỏi nữa, làm thế nào để làm điều đó trong một danh sách như thế này:[['Aden'], ['abel']]

Có phải mỗi danh sách chỉ có một mục? Nếu vậy, chỉ cần sửa đổi một chút thành:sorted(x,key=lambda i:i[0].lower())
jamylak

Chà, nó cũng có thể có một số thứ khác, không nên sử dụng để sắp xếp.

1
Không bao giờ, có vẻ như tôi đã sai, việc sắp xếp không hoạt động đối với cả chuỗi và unicode, tôi đã nhầm lẫn với một câu hỏi trước đó trong đó các bộ dữ liệu cũng được bao gồm trong sắp xếp.
jamylak

10

Bạn cũng có thể thử cách này để sắp xếp danh sách tại chỗ:

>>> x = ['Aden', 'abel']
>>> x.sort(key=lambda y: y.lower())
>>> x
['abel', 'Aden']


3

Trong python3 bạn có thể sử dụng

list1.sort(key=lambda x: x.lower()) #Case In-sensitive             
list1.sort() #Case Sensitive

1

Tôi đã làm theo cách này cho Python 3.3:

 def sortCaseIns(lst):
    lst2 = [[x for x in range(0, 2)] for y in range(0, len(lst))]
    for i in range(0, len(lst)):
        lst2[i][0] = lst[i].lower()
        lst2[i][1] = lst[i]
    lst2.sort()
    for i in range(0, len(lst)):
        lst[i] = lst2[i][1]

Sau đó, bạn chỉ có thể gọi chức năng này:

sortCaseIns(yourListToSort)

0

Sắp xếp không phân biệt chữ hoa chữ thường, sắp xếp chuỗi tại chỗ , trong Python 2 OR 3 (được thử nghiệm trong Python 2.7.17 và Python 3.6.9):

>>> x = ["aa", "A", "bb", "B", "cc", "C"]
>>> x.sort()
>>> x
['A', 'B', 'C', 'aa', 'bb', 'cc']
>>> x.sort(key=str.lower)           # <===== there it is!
>>> x
['A', 'aa', 'B', 'bb', 'C', 'cc']

Điều quan trọng là key=str.lower. Đây là những lệnh đó trông như thế nào chỉ với các lệnh, để dễ dàng sao chép để bạn có thể kiểm tra chúng:

x = ["aa", "A", "bb", "B", "cc", "C"]
x.sort()
x
x.sort(key=str.lower)
x

Lưu ý rằng nếu các chuỗi của bạn là các chuỗi unicode, tuy nhiên (như u'some string'), thì chỉ trong Python 2 (KHÔNG phải trong Python 3 trong trường hợp này), x.sort(key=str.lower)lệnh trên sẽ thất bại và xuất ra lỗi sau:

TypeError: descriptor 'lower' requires a 'str' object but received a 'unicode'

Nếu bạn gặp lỗi này, thì hãy nâng cấp lên Python 3 nơi chúng xử lý sắp xếp unicode hoặc chuyển đổi chuỗi unicode của bạn thành chuỗi ASCII trước, bằng cách sử dụng cách hiểu danh sách, như sau:

# for Python2, ensure all elements are ASCII (NOT unicode) strings first
x = [str(element) for element in x]  
# for Python2, this sort will only work on ASCII (NOT unicode) strings
x.sort(key=str.lower)

Người giới thiệu:

  1. https://docs.python.org/3/l Library / stdtypes.html#list.sort
  2. Chuyển đổi một chuỗi Unicode thành một chuỗi trong Python (chứa các ký hiệu bổ sung)
  3. https://www.programiz.com/python-programming/list-comp Hiểu

-3

Thử cái này

def cSort(inlist, minisort=True):
    sortlist = []
    newlist = []
    sortdict = {}
    for entry in inlist:
        try:
            lentry = entry.lower()
        except AttributeError:
            sortlist.append(lentry)
        else:
            try:
                sortdict[lentry].append(entry)
            except KeyError:
                sortdict[lentry] = [entry]
                sortlist.append(lentry)

    sortlist.sort()
    for entry in sortlist:
        try:
            thislist = sortdict[entry]
            if minisort: thislist.sort()
            newlist = newlist + thislist
        except KeyError:
            newlist.append(entry)
    return newlist

lst = ['Aden', 'abel']
print cSort(lst)

Đầu ra

['abel', 'Aden']


9
Giải pháp này là quá mức cần thiết và không thể đọc được khi một lớp lót đủ. Điều này có thể được chấp nhận hơn trong một ngôn ngữ khác Python.
IceArdor
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.