sortowanie list bez uwzględniania wielkości liter, bez zmniejszania wyniku?


133

Mam listę ciągów takich jak ta:

['Aden', 'abel']

Chcę posortować elementy bez rozróżniania wielkości liter. Więc chcę dostać:

['abel', 'Aden']

Ale w przypadku sorted()lub jest odwrotnie list.sort(), ponieważ wielkie litery pojawiają się przed małymi.

Jak mogę zignorować sprawę? Widziałem rozwiązania polegające na zmniejszaniu wielkości liter wszystkich elementów listy, ale nie chcę zmieniać wielkości liter w elementach listy.


Ten samouczek jest bardzo pomocny: docs.python.org/3/howto/sorting.html#sortinghowto
ady

Odpowiedzi:


192

W Pythonie 3.3+ istnieje str.casefoldmetoda zaprojektowana specjalnie do dopasowywania bezkrytycznego:

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

W Pythonie 2 użyj lower():

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

Działa zarówno dla ciągów normalnych, jak i znaków Unicode, ponieważ oba mają lowermetodę.

W Pythonie 2 działa dla mieszanki ciągów normalnych i Unicode, ponieważ wartości obu typów można porównywać ze sobą. Jednak Python 3 nie działa w ten sposób: nie można porównywać ciągu bajtów i ciągu znaków Unicode, więc w Pythonie 3 należy postępować rozsądnie i sortować listy tylko jednego typu ciągu.

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

11
Można uniknąć okrążania funkcji lambda przez (Python 3) używając str.lowerfunkcji ogólnej as sorted(lst, key=str.lower)or (Python 2) używając lowermetody stringmodułu as sorted(lst, key=string.lower). Można również użyć str.lowerdla łańcuchów w Pythonie 2, ale wtedy musiałoby to być użyte unicode.lowerdla unicodeobiektów, podczas gdy string.lowerakceptuje oba (co, jak to ująłeś, prawdopodobnie nie jest tak naprawdę "rozsądnym" trybem działania).
Daniel Andersson

To nie zadziała w przypadku listy takiej jak [„Z”, „B”, „a”, „b”, „A”], która jest sortowana do [„a”, „A”, „B”, „b”, „Z”]. Wielka litera „B” pojawia się przed małą literą „b”, ponieważ funkcje sort () i sort () w Pythonie zachowują pierwotną kolejność, gdy ciągi pasują do siebie. W tym przypadku uważa się, że wielkie litery „B” pasują do małej litery „b”, gdy używane jest zawijanie liter. Dzieje się tak zawsze, gdy konwertujesz wielkość liter w celu porównania: posortowane (spam, klucz = str.lower) lub posortowane (spam, klucz = str.w górę) lub posortowane (spam, klucz = str.casefold).
PJ Singh

Zamiast tego wypróbuj to rozwiązanie: stackoverflow.com/a/1098160/10668287 . Spowoduje to prawidłowe posortowanie [„Aden”, „aden”] jako [„aden”, „Aden”].
PJ Singh

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

W Pythonie 3 strjest to Unicode, ale w Pythonie 2 możesz użyć tego bardziej ogólnego podejścia, które działa zarówno w przypadku, jak stri unicode:

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

Dziękuję Ci. Wiem, że powinienem był o tym wspomnieć wcześniej, ale słyszałem, że jest problem z użyciem tej metody na łańcuchu znaków Unicode (Py2). Wiesz coś o tym?

Wszystkie są unicode. Dzięki! Jeszcze jedno pytanie, jak to zrobić na liście takiej jak ta:[['Aden'], ['abel']]

Czy każda lista zawiera tylko jedną pozycję? Jeśli tak, po prostu zmodyfikuj to trochę, aby:sorted(x,key=lambda i:i[0].lower())
jamylak

Cóż, może zawierać również inne rzeczy, których jednak nie należy używać do sortowania.

1
Nieważne, wygląda na to, że się myliłem, sortowanie działa dla mieszanki zarówno stringów, jak i Unicode, pomyliłem się z poprzednim pytaniem, w którym krotki również były uwzględnione w sortowaniu.
jamylak

10

Możesz także spróbować posortować listę lokalnie:

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


3

W python3 możesz użyć

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

1

Zrobiłem to w ten sposób dla Pythona 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]

Następnie możesz po prostu wywołać tę funkcję:

sortCaseIns(yourListToSort)

0

Sortowanie bez rozróżniania wielkości liter, sortowanie ciągu w miejscu , w Pythonie 2 LUB 3 (testowane w Pythonie 2.7.17 i Pythonie 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']

Klucz jest key=str.lower. Oto, jak wyglądają te polecenia tylko z poleceniami, co ułatwia kopiowanie i wklejanie, aby można było je przetestować:

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

Zauważ, że jeśli twoje ciągi są ciągami znaków Unicode (jak u'some string'), to tylko w Pythonie 2 (NIE w Pythonie 3 w tym przypadku) powyższe x.sort(key=str.lower)polecenie zakończy się niepowodzeniem i wyświetli następujący błąd:

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

Jeśli pojawi się ten błąd, albo zaktualizuj do Pythona 3, w którym obsługuje sortowanie Unicode, lub najpierw przekonwertuj ciągi znaków Unicode na ciągi ASCII, używając funkcji rozumienia list, na przykład:

# 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)

Bibliografia:

  1. https://docs.python.org/3/library/stdtypes.html#list.sort
  2. Konwertuj ciąg Unicode na ciąg w Pythonie (zawierający dodatkowe symbole)
  3. https://www.programiz.com/python-programming/list-comprehension

-3

Spróbuj tego

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)

Wynik

['abel', 'Aden']


9
To rozwiązanie jest przesadne i nieczytelne, gdy wystarczy jednolinijkowy. Może to być bardziej akceptowalne w języku innym niż Python.
IceArdor,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.