сортировка списков без учета регистра без уменьшения результата?


135

У меня есть список таких строк:

['Aden', 'abel']

Я хочу отсортировать элементы без учета регистра. Итак, я хочу получить:

['abel', 'Aden']

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

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


Этот учебник очень полезен: docs.python.org/3/howto/sorting.html#sortinghowto
— ady

Ответы:


195

В 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())

Он работает как для обычных строк, так и для строк в Юникоде, поскольку у них обоих есть lowerметод.

В Python 2 он работает с сочетанием обычных строк и строк в Юникоде, поскольку значения двух типов можно сравнивать друг с другом. Однако 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принимает оба (что, как вы выразились, вероятно, не совсем «нормальный» режим работы).
— Daniel Andersson

Это не сработает для таких списков, как ['Z', 'B', 'a', 'b', 'A'], которые сортируются по ['a', 'A', 'B', 'b', 'Z']. Заглавная «B» появляется перед строчной «b», потому что функции sort () и sorted () Python сохраняют исходный порядок при совпадении строк. В этом случае заглавная буква «B» считается соответствующей строчной букве «b» при использовании casefold. Это всегда происходит, если вы конвертируете регистр для сравнения: отсортированный (спам, ключ = 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используется unicode, но в 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
Неважно, похоже, я был неправ, сортировка работает для сочетания строк и юникода, меня смутил предыдущий вопрос, в котором кортежи также были включены в сортировку.
— 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-comprehension

-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.