сортування списку без урахування регістру, не знижуючи результат?


134

У мене є список таких рядків:

['Aden', 'abel']

Я хочу сортувати предмети, не залежні від регістру. Тому я хочу отримати:

['abel', 'Aden']

Але я отримую протилежне з sorted()або list.sort(), тому що великі регістри постають перед малі.

Як я можу проігнорувати випадок? Я бачив рішення, що передбачають зменшення розміру всіх елементів списку, але я не хочу змінювати регістр елементів списку.


Цей підручник дуже корисний: docs.python.org/3/howto/sorting.html#sortinghowto
ady

Відповіді:


194

У Python 3.3+ є str.casefoldметод, спеціально розроблений для безвідповідної відповідності:

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

У Python 2 використовуйте lower():

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

Він працює як для звичайних, так і для Unicode рядків, оскільки в обох є lowerметод.

У Python 2 він працює для поєднання нормальних і unicode рядків, оскільки значення двох типів можна порівняти один з одним. Python 3, однак, не працює так: ви не можете порівнювати рядок байтів і рядок unicode, тому в Python 3 слід робити здорові речі і лише сортувати списки одного типу рядків.

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

11
Можна уникнути прямолінійної функції лямбда шляхом (Python 3), використовуючи загальну str.lowerфункцію як sorted(lst, key=str.lower)або (Python 2), використовуючи lowerметод stringмодуля як sorted(lst, key=string.lower). Можна також використовувати str.lowerдля рядків у Python 2, але тоді доведеться використовувати unicode.lowerдля unicodeоб'єктів, тоді як string.lowerприймає і те, і інше, як ви сказали, мабуть, не є «розумним» режимом роботи.
Даніель Андерссон

Це не працює для списку типу "Z", "B", "a", "b", "A"], який сортується до ['a', 'A', 'B', 'b', 'Z']. Велика літера "B" з'являється перед рядком "b", оскільки сорти () та сортування () Python зберігають початковий порядок, коли рядки збігаються. У цьому випадку велика величина "B" вважається такою, що відповідає малій літери "b" при використанні регістру. Це завжди відбувається, якщо ви конвертуєте регістр для порівняння: відсортований (спам, ключ = str.lower) або відсортований (спам, ключ = str.upper) або відсортований (спам, ключ = str.casefold).
PJ Singh

Спробуйте замість цього рішення: stackoverflow.com/a/1098160/10668287 . Він буде сортувати ['Aden', 'aden'] правильно як ['aden', 'Aden'].
PJ Singh

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

В Python 3 strЮникода , але в Python 2 ви можете використовувати цей більш загальний підхід , який працює для обох strі unicode:

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

Дякую. Я знаю, що я повинен був згадувати про це раніше, але я чув, що існує проблема із використанням цього методу в рядку Unicode (Py2). Ви щось знаєте про це?

Всі вони є однокольоровими. Дякую! Ще одне питання, як це зробити у такому списку:[['Aden'], ['abel']]

Чи є в кожному списку лише один предмет? Якщо так, просто змініть його на:sorted(x,key=lambda i:i[0].lower())
jamylak

Що ж, у нього можуть бути й інші речі, які не слід використовувати для сортування.

1
Незважаючи на те, здається, я помилявся, сортування працює за сумішшю рядків і Unicode, я був плутаний з попереднім питанням, коли кортежі також були включені до сортування.
jamylak

10

Ви також можете спробувати це для сортування списку на місці:

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


3

У python3 ви можете використовувати

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

1

Я зробив це так для 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]

Тоді ви просто можете викликати цю функцію:

sortCaseIns(yourListToSort)

0

Нечутливий до регістру сортування рядка на місці в Python 2 OR 3 (тестований у Python 2.7.17 та 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']

Ключовим є key=str.lower. Ось як виглядають ці команди за допомогою лише цих команд, щоб легко вставити копію, щоб ви могли їх перевірити:

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

Зауважте, що якщо ваші рядки є рядками Unicode (окрім u'some string'), то лише в Python 2 (у цьому випадку НЕ в Python 3) вищевказана x.sort(key=str.lower)команда не вдасться і виведе наступну помилку:

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

Якщо ви отримаєте цю помилку, то або перейдіть на Python 3, де вони обробляють сортування Unicode, або перетворіть ваші рядки Unicode в рядки ASCII спочатку, використовуючи розуміння списку, як це:

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

Список літератури:

  1. https://docs.python.org/3/library/stdtypes.html#list.sort
  2. Перетворити рядок Unicode в рядок на Python (містить додаткові символи)
  3. https://www.programiz.com/python-programming/list-conservation

-3

Спробуйте це

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)

Вихідні дані

['abel', 'Aden']


9
Це рішення є надмірним і нечитабельним, коли вистачає одноколірного. Це може бути більш прийнятним мовою, відмінною від Python.
IceArdor
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.