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


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.