ordinamento di elenchi senza distinzione tra maiuscole e minuscole, senza minare il risultato?


133

Ho un elenco di stringhe come questa:

['Aden', 'abel']

Voglio ordinare gli articoli, senza distinzione tra maiuscole e minuscole. Quindi voglio ottenere:

['abel', 'Aden']

Ma ottengo il contrario con sorted()o list.sort(), perché il maiuscolo appare prima del minuscolo.

Come posso ignorare il caso? Ho visto soluzioni che comportano la riduzione in minuscolo di tutti gli elementi dell'elenco, ma non voglio cambiare il caso degli elementi dell'elenco.


Questo tutorial è molto utile: docs.python.org/3/howto/sorting.html#sortinghowto
ady,

Risposte:


192

In Python 3.3+ esiste il str.casefoldmetodo specificamente progettato per la corrispondenza senza cas:

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

In Python 2 usa lower():

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

Funziona sia con stringhe normali che unicode, poiché entrambe hanno un lowermetodo.

In Python 2 funziona per un mix di stringhe normali e unicode, poiché i valori dei due tipi possono essere confrontati tra loro. Python 3 non funziona in questo modo, però: non puoi confrontare una stringa di byte e una stringa unicode, quindi in Python 3 dovresti fare la cosa sana e ordinare solo gli elenchi di un tipo di stringa.

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

11
Si può evitare la funzione lambda andata e ritorno da (Python 3) usando la str.lowerfunzione generale come sorted(lst, key=str.lower)o (Python 2) usando il lowermetodo del stringmodulo comesorted(lst, key=string.lower) . Si può anche usare str.lowerper le stringhe in Python 2, ma poi dovrebbe usare unicode.lowerper gli unicodeoggetti, mentre string.loweraccetta entrambi (che, come dici tu, probabilmente non è in realtà una modalità di funzionamento "sana").
Daniel Andersson,

Ciò non funzionerebbe per un elenco come ['Z', 'B', 'a', 'b', 'A'], che ordina in ['a', 'A', 'B', 'b', 'Z']. La 'B' maiuscola appare prima della 'b' minuscola perché l'ordinamento () e l'ordinamento () di Python conservano l'ordine originale quando le stringhe corrispondono. In questo caso, la maiuscola "B" è considerata corrispondente alla "b" minuscola quando si utilizza la cartella. Questo accade sempre se si converte il caso per confrontare: ordinato (spam, chiave = str.lower) o ordinato (spam, chiave = str.upper) o ordinato (spam, chiave = str.casefold).
PJ Singh,

Prova invece questa soluzione: stackoverflow.com/a/1098160/10668287 . Ordinerà ['Aden', 'aden'] correttamente come ['aden', 'Aden'].
PJ Singh,

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

In Python 3 strè unicode ma in Python 2 è possibile utilizzare questo approccio più generale che funziona per entrambi stre unicode:

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

Grazie. So che avrei dovuto menzionarlo prima, ma ho sentito che c'è un problema con l'uso di questo metodo su una stringa unicode (Py2). Ne sai qualcosa?

Sono tutti unicode. Grazie! Ancora una domanda, come farlo in un elenco come questo:[['Aden'], ['abel']]

Ogni elenco ha un solo oggetto? In tal caso, modificalo un po 'per:sorted(x,key=lambda i:i[0].lower())
jamylak,

Bene, potrebbe anche avere altre cose, che non dovrebbero essere utilizzate per l'ordinamento.

1
Non importa, sembra che mi sbagliassi, l'ordinamento funziona per un mix di stringhe e unicode, ero confuso con una domanda precedente in cui anche le tuple erano incluse nell'ordinamento.
jamylak,

10

Puoi anche provare questo per ordinare l'elenco sul posto:

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


3

In python3 puoi usare

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

1

L'ho fatto in questo modo per 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]

Quindi puoi semplicemente chiamare questa funzione:

sortCaseIns(yourListToSort)

0

Ordinamento senza distinzione tra maiuscole e minuscole, ordinamento della stringa in atto , in Python 2 OR 3 (testato in Python 2.7.17 e 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']

La chiave è key=str.lower. Ecco come appaiono questi comandi con solo i comandi, per un facile copia-incolla in modo da poterli testare:

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

Nota che se le tue stringhe sono stringhe unicode, comunque (come u'some string'), solo in Python 2 (NON in Python 3 in questo caso) il x.sort(key=str.lower)comando sopra fallirà e produrrà il seguente errore:

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

Se ricevi questo errore, esegui l'upgrade a Python 3 dove gestiscono l'ordinamento unicode o converti prima le stringhe unicode in stringhe ASCII, usando una comprensione dell'elenco, come questa:

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

Riferimenti:

  1. https://docs.python.org/3/library/stdtypes.html#list.sort
  2. Converti una stringa Unicode in una stringa in Python (contenente simboli extra)
  3. https://www.programiz.com/python-programming/list-comprehension

-3

Prova questo

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)

Produzione

['abel', 'Aden']


9
Questa soluzione è eccessiva e illeggibile quando è sufficiente una sola riga. Questo potrebbe essere più accettabile in una lingua diversa da Python.
IceArdor,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.