ordenación de listas sin distinción entre mayúsculas y minúsculas, sin minúsculas el resultado?

133

Tengo una lista de cadenas como esta:

['Aden', 'abel']

Quiero ordenar los elementos, sin distinción entre mayúsculas y minúsculas. Entonces quiero obtener:

['abel', 'Aden']

Pero obtengo lo contrario con sorted()o list.sort(), porque las mayúsculas aparecen antes que las minúsculas.

¿Cómo puedo ignorar el caso? He visto soluciones que implican minúsculas todos los elementos de la lista, pero no quiero cambiar el caso de los elementos de la lista.

jamylak
fuente
Este tutorial es muy útil: docs.python.org/3/howto/sorting.html#sortinghowto
ady

Respuestas:

192

En Python 3.3+ existe el str.casefoldmétodo diseñado específicamente para la coincidencia sin mayúsculas y minúsculas:

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

En Python 2 use lower():

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

Funciona para cadenas normales y unicode, ya que ambas tienen un lowermétodo.

En Python 2 funciona para una combinación de cadenas normales y unicode, ya que los valores de los dos tipos se pueden comparar entre sí. Sin embargo, Python 3 no funciona así: no puede comparar una cadena de bytes y una cadena Unicode, por lo que en Python 3 debe hacer lo correcto y solo ordenar las listas de un tipo de cadena.

>>> lst = ['Aden', u'abe1']
>>> sorted(lst)
['Aden', u'abe1']
>>> sorted(lst, key=lambda s: s.lower())
[u'abe1', 'Aden']
John Kugelman
fuente
11
Se puede evitar el viaje de ida y vuelta de la función lambda (Python 3) usando la str.lowerfunción general as sorted(lst, key=str.lower)o (Python 2) usando el lowermétodo del stringmódulo como sorted(lst, key=string.lower). También se puede usar str.lowerpara cadenas en Python 2, pero luego se tendría que usar unicode.lowerpara unicodeobjetos, mientras que se string.loweraceptan ambas (lo cual, como se dice, probablemente no sea realmente un modo de operación "sensato").
Daniel Andersson
Esto no funcionaría para una lista como ['Z', 'B', 'a', 'b', 'A'], que se clasifica como ['a', 'A', 'B', 'b', 'Z']. La 'B' mayúscula aparece antes de la 'b' minúscula porque sort () y sorted () de Python conservan el orden original cuando las cadenas coinciden. En este caso, se considera que la 'B' mayúscula coincide con la 'b' minúscula cuando se usa el plegado en mayúsculas. Esto siempre sucede si convierte mayúsculas y minúsculas para comparar: ordenado (spam, clave = str.lower) o ordenado (spam, clave = str.upper) o ordenado (spam, clave = str.casefold).
PJ Singh
Pruebe esta solución en su lugar: stackoverflow.com/a/1098160/10668287 . Clasificará ['Aden', 'aden'] correctamente como ['aden', 'Aden'].
PJ Singh
46
>>> x = ['Aden', 'abel']
>>> sorted(x, key=str.lower) # Or unicode.lower if all items are unicode
['abel', 'Aden']

En Python 3 stres Unicode, pero en Python 2 se puede utilizar este enfoque más general que funcione para ambos stry unicode:

>>> sorted(x, key=lambda s: s.lower())
['abel', 'Aden']
jamylak
fuente
Gracias. Sé que debería haber mencionado esto antes, pero he oído que hay un problema con el uso de este método en una cadena Unicode (Py2). ¿Sabes algo de eso?
Todos son unicode. ¡Gracias! Una pregunta más, cómo hacerlo en una lista como esta:[['Aden'], ['abel']]
¿Cada lista solo tiene un elemento? Si es asísorted(x,key=lambda i:i[0].lower())
modifíquelo
Bueno, también podría tener algunas otras cosas, que no deberían usarse para la clasificación.
1
No importa, parece que estaba equivocado, la clasificación funciona para una combinación de cadenas y unicode, me confundieron con una pregunta anterior donde las tuplas también se incluyeron en el orden.
jamylak
10

También puede intentar esto para ordenar la lista en el lugar:

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

En python3 puedes usar

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

Lo hice de esta manera para 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]

Entonces puedes llamar a esta función:

sortCaseIns(yourListToSort)
Alexey Gorozhanov
fuente
0

Clasificación sin distinción entre mayúsculas y minúsculas, ordenando la cadena en su lugar , en Python 2 O 3 (probado en Python 2.7.17 y 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 clave es key=str.lower. Así es como se ven esos comandos con solo los comandos, para copiar y pegar fácilmente para que pueda probarlos:

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

Tenga en cuenta que si sus cadenas son cadenas Unicode, sin embargo (como u'some string'), solo en Python 2 (NO en Python 3 en este caso) el x.sort(key=str.lower)comando anterior fallará y generará el siguiente error:

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

Si obtiene este error, actualice a Python 3, donde manejan la clasificación unicode, o convierta sus cadenas unicode a cadenas ASCII primero, usando una comprensión 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)

Referencias

  1. https://docs.python.org/3/library/stdtypes.html#list.sort
  2. Convierta una cadena Unicode en una cadena en Python (que contiene símbolos adicionales)
  3. https://www.programiz.com/python-programming/list-comprehension
Gabriel Staples
fuente
-3

Prueba esto

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)

Salida

['abel', 'Aden']

Espejismo
fuente
9
Esta solución es exagerada e ilegible cuando basta una sola línea. Esto podría ser más aceptable en un lenguaje que no sea Python.
IceArdor