classificação de lista sem distinção entre maiúsculas e minúsculas, sem minúsculas no resultado?

133

Eu tenho uma lista de seqüências de caracteres como esta:

['Aden', 'abel']

Quero classificar os itens, sem distinção entre maiúsculas e minúsculas. Então, eu quero obter:

['abel', 'Aden']

Mas entendo o contrário com sorted()or list.sort(), porque maiúsculas aparece antes de minúsculas.

Como posso ignorar o caso? Vi soluções que envolvem letras minúsculas em todos os itens da lista, mas não quero alterar o caso dos itens da lista.

jamylak
fonte
Este tutorial é muito útil: docs.python.org/3/howto/sorting.html#sortinghowto
ady

Respostas:

192

No Python 3.3 ou superior, existe o str.casefoldmétodo projetado especificamente para correspondência sem caixa:

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

No Python 2, use lower():

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

Funciona para cadeias normais e unicode, pois ambas possuem um lowermétodo.

No Python 2, ele funciona para uma mistura de cadeias normais e unicode, já que os valores dos dois tipos podem ser comparados entre si. O Python 3 não funciona assim: você não pode comparar uma sequência de bytes e uma sequência unicode; portanto, no Python 3 você deve fazer a coisa sã e classificar apenas as listas de um tipo de sequência.

>>> lst = ['Aden', u'abe1']
>>> sorted(lst)
['Aden', u'abe1']
>>> sorted(lst, key=lambda s: s.lower())
[u'abe1', 'Aden']
John Kugelman
fonte
11
Pode-se evitar a ida e volta da função lambda usando (Python 3) usando a str.lowerfunção geral como sorted(lst, key=str.lower)ou (Python 2) usando o lowermétodo do stringmódulo como sorted(lst, key=string.lower). Também se pode usar str.lowerpara strings no Python 2, mas seria necessário usar unicode.lowerpara unicodeobjetos, enquanto string.loweraceita os dois (o que, como você disse, provavelmente não é realmente um modo de operação "saudável").
Daniel Andersson
Isso não funcionaria para uma lista como ['Z', 'B', 'a', 'b', 'A'], que classifica como ['a', 'A', 'B', 'b', 'Z']. A maiúscula 'B' aparece antes da minúscula 'b' porque sort () e ordenada () do Python preservam a ordem original quando as cadeias correspondem. Nesse caso, considera-se que o capital 'B' corresponde ao minúsculo 'b' ao usar a dobra de caixa. Isso sempre acontece se você converter maiúsculas e minúsculas para comparar: classificado (spam, chave = str.lower) ou classificado (spam, chave = str.upper) ou classificado (spam, chave = str.casefold).
PJ Singh
Tente esta solução: stackoverflow.com/a/1098160/10668287 . Ele classificará ['Aden', 'aden'] corretamente como ['aden', 'Aden'].
PJ Singh
46
>>> x = ['Aden', 'abel']
>>> sorted(x, key=str.lower) # Or unicode.lower if all items are unicode
['abel', 'Aden']

No Python 3 stré unicode, mas no Python 2 você pode usar essa abordagem mais geral que funciona para ambos stre unicode:

>>> sorted(x, key=lambda s: s.lower())
['abel', 'Aden']
jamylak
fonte
Obrigado. Eu sei que deveria ter mencionado isso antes, mas ouvi dizer que há um problema com o uso desse método em uma string unicode (Py2). Você sabe alguma coisa sobre isso?
Eles são todos unicode. Obrigado! Mais uma pergunta, como fazê-lo em uma lista como esta:[['Aden'], ['abel']]
Cada lista possui apenas um item? Se tão apenas modificá-lo um pouco para:sorted(x,key=lambda i:i[0].lower())
jamylak
Bem, ele pode ter outras coisas também, que não devem ser usadas para classificação.
1
Deixa pra lá, parece que eu estava errado, a classificação funciona para uma mistura de strings e unicode, fiquei confuso com uma pergunta anterior em que as tuplas também foram incluídas na classificação.
jamylak
10

Você também pode tentar fazer isso para classificar a lista no local:

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

Em python3 você pode usar

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

Eu fiz dessa maneira para o 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]

Então você pode chamar esta função:

sortCaseIns(yourListToSort)
Alexey Gorozhanov
fonte
0

Classificação sem distinção entre maiúsculas e minúsculas, classificando a sequência no lugar , no Python 2 OR 3 (testado no 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']

A chave é key=str.lower. Veja como esses comandos são apenas os comandos, para facilitar a cópia e colar para que você possa testá-los:

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

Observe que, se suas strings forem unicode, no entanto (como u'some string'), somente no Python 2 (não no Python 3 neste caso), o x.sort(key=str.lower)comando acima falhará e emitirá o seguinte erro:

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

Se você receber esse erro, atualize para o Python 3, onde eles lidam com a classificação unicode, ou converta suas strings unicode em strings ASCII primeiro, usando uma compreensão de lista, como esta:

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

Referências:

  1. https://docs.python.org/3/library/stdtypes.html#list.sort
  2. Converter uma string Unicode em uma string em Python (contendo símbolos extras)
  3. https://www.programiz.com/python-programming/list-comprehension
Gabriel Staples
fonte
-3

Tente isto

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)

Resultado

['abel', 'Aden']

Miragem
fonte
9
Essa solução é um exagero e ilegível quando uma linha é suficiente. Isso pode ser mais aceitável em uma linguagem diferente do Python.
IceArdor 07/02