Страницы

Поиск по вопросам

воскресенье, 2 февраля 2020 г.

Неверный порядок сортировки списка строк в python

#python #строки #сортировка


Доброго времени суток. Я совсем недавно начал изучать python, поэтому прошу не кидать
камнями, если я упускаю что-то очевидное. Гугл с моим вопросом не помог. Дело в том,
что сортировка списка строк, которая, по идее, должна проводиться по алфавиту, но у
меня происходит не совсем по нему. И я никак не пойму, отчего так. Вот есть, допустим,
у меня такой код

inp = open("input", "r")
outp = open("output", "w")
lst = inp.read().split()
lst.sort()
for elem in lst:
    outp.write(str(elem) + "\n")
inp.close()
outp.close()


В файле input у меня набор слов, по слову на каждой строке. Допустим, есть файл с
такими данными(просто белиберда для проверки):

авыаы
мрпр
квуенуке
авпвке
цуеек
авыронг
авроанг
аыуке
гекекы
енгнкекв
ывавкеекц
огшдн
цййап
выама
пенк
иаапре
аукег
венгера
вкыкавп43у
авапнеанне
ноорвап
ававыпен


А в файле output я получаю вот это:

ававыпен
авапнеанне
авпвке
авроанг
авыаы
авыронг
аукег
аыуке
енгнкекв
ноорвап
венгера
вкыкавп43у
выама
иаапре
квуенуке
огшдн
гекекы
пенк
мрпр
цййап
цуеек
ывавкеекц


Ну вот какого черта, например, "венгера" идет после "ноорвап", ведь слова на букву
"в" должны находиться перед словами на букву "н"? Также выходит, что слова на букву
"и" идут после слов на букву "к", что, очевидно, неверно. И т.д. и т.п. Вроде бы слова
на одну и ту же букву действительно "собрались вместе", то есть сортировка по алфавиту
была произведена, вот только алфавит какой-то не такой. Помогите, пожалуйста, понять,
что я делаю не так.

Update: Когда я решил просто вывести отсортированные буквы алфавита то получил это:

а б е ж з л н в и к о г п м д й р с ъ ь ю э я у т ф ц ч х щ ы ш


У python какой-то непонятно откуда взявшийся свой алфавит. Что это вообще значит?

При попытке сменить локаль при помощи locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')
python выдает ошибку

Traceback (most recent call last):
  File "search2.py", line 24, in 
    locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')
  File 
"C:\Users\andre\AppData\Local\Programs\Python\Python36\lib\locale.py", line 
598, in setlocale
    return _setlocale(category, locale)
locale.Error: unsupported locale setting

    


Ответы

Ответ 1



Ваш файл input сохранён в кодировке UTF-8. Когда вы не указываете кодировку файла явно в методе open, питон для чтения или записи файла выбирает некую кодировку по умолчанию, которая зависит от системы. В вашем случае в винде этой кодировкой оказалась не UTF-8, а cp1251. В результате питон прочитал ваш файл в неправильной кодировке, и получилось вот так: авыаы РјСЂРїСЂ квуенуке авпвке цуеек авыронг авроанг аыуке гекекы енгнкекв ывавкеекц огшдн цййап выама пенк иаапре аукег венгера вкыкавп43Сѓ авапнеанне ноорвап ававыпен Соответственно и правила сортировки изменились. Наиболее простым и предпочтительным способом исправления этого будет явное указание кодировки файла при чтении: inp = open("input", "r", encoding="utf-8-sig") (Я указал utf-8-sig вместо utf-8, чтобы питон нормально обработал BOM, который любит добавлять виндовый Блокнот.) Да и для записи желательно проделать то же самое: outp = open("output", "w", encoding="utf-8") (Здесь я указал utf-8 вместо utf-8-sig, чтобы BOM в выходной файл не добавлялся. Можете изменить это на свой вкус.) Если вы хотите использовать другие кодировки в своих файлах, замените их на свои соответственно.

Ответ 2



Основной ответ: mylist = ["b", "C", "A"] mylist.sort() Это изменяет исходный список. Чтобы получить отсортированную копию списка без изменения оригинала, используйте функцию sorted (): for x in sorted(mylist): print x Однако приведенные выше примеры немного наивны, потому что они не учитывают языковой стандарт и выполняют сортировку по регистру. Вы можете воспользоваться опциональным ключом параметра, чтобы указать пользовательский порядок сортировки (например, использование cmp является устаревшим решением, поскольку его нужно оценивать несколько раз - ключ вычисляется только один раз для каждого элемента). Итак, для сортировки в соответствии с текущей локалью, принимая во внимание специфические для языка правила (cmp_to_key - вспомогательная функция от functools): sorted(mylist, key=cmp_to_key(locale.strcoll)) И, наконец, если вам нужно, вы можете указать пользовательскую локаль для сортировки: import locale locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') # vary depending on your lang/locale assert sorted( (u'Ab', u'ad', u'aa'), key=cmp_to_key(locale.strcoll) ) == [u'aa', u'Ab', u'ad'] Последнее замечание: вы можете глянуть примеры нечувствительности к регистру сортировки, которые используют метод lower() - они неверны, поскольку работают только для подмножества символов ASCII. Эти два неверны для любых неанглийских данных: # this is incorrect! mylist.sort(key=lambda x: x.lower()) # alternative notation, a bit faster, but still wrong mylist.sort(key=str.lower) Замечание. В некоторых случаях локаль следует указывать как: locale.setlocale(locale.LC_ALL, 'ru_RU.utf8')

Комментариев нет:

Отправить комментарий