Как отсортировать по алфавиту строки Unicode в Python?
Python сортирует по значению байта по умолчанию, что означает, что é приходит после z и других не менее забавных вещей. Каков наилучший способ сортировки в алфавитном порядке в Python?
есть ли библиотека для этого? Я ничего не смог найти. Предпочтительно сортировка должна иметь поддержку языка, поэтому он понимает, что åäö должен быть отсортирован после z на шведском языке, но что ü должен быть отсортирован по u и т. д. Таким образом, поддержка Unicode является в значительной степени требованием.
Если для него нет библиотеки, то что это лучший способ сделать это? Просто сделайте сопоставление из Буквы в целое значение и сопоставьте строку с целочисленным списком с этим?
11 ответов:
IBM ICU библиотека это (и многое другое). Он имеет привязки Python: PyICU.
обновление: основная разница в сортировке между ICU и
locale.strcoll
это то, что ICU использует полный Алгоритм Сортировки Юникода покаstrcoll
использует ISO 14651.различия между этими двумя алгоритмами кратко изложены здесь:http://unicode.org/faq/collation.html#13. это довольно экзотические частные случаи, которые редко должны иметь значение на практике.
>>> import icu # pip install PyICU >>> sorted(['a','b','c','ä']) ['a', 'b', 'c', 'ä'] >>> collator = icu.Collator.createInstance(icu.Locale('de_DE.UTF-8')) >>> sorted(['a','b','c','ä'], key=collator.getSortKey) ['a', 'ä', 'b', 'c']
Я не вижу в ответах. Мое приложение сортируется в соответствии с языковым стандартом, используя стандартную библиотеку python. Это довольно легко.
# python2.5 code below # corpus is our unicode() strings collection as a list corpus = [u"Art", u"Älg", u"Ved", u"Wasa"] import locale # this reads the environment and inits the right locale locale.setlocale(locale.LC_ALL, "") # alternatively, (but it's bad to hardcode) # locale.setlocale(locale.LC_ALL, "sv_SE.UTF-8") corpus.sort(cmp=locale.strcoll) # in python2.x, locale.strxfrm is broken and does not work for unicode strings # in python3.x however: # corpus.sort(key=locale.strxfrm)
вопрос к Леннарту и другим ответчикам: неужели никто не знает "locale" или это не соответствует этой задаче?
попробуйте Джеймса Таубера Алгоритм Сортировки Юникода Python. Это может быть не совсем так, как вы хотите, но, кажется, стоит посмотреть. Дополнительные сведения о проблемах см. В разделе этот пост Кристофер Ленц.
вы также можете быть заинтересованы в pyuca:
http://jtauber.com/blog/2006/01/27/python_unicode_collation_algorithm/
хотя это, конечно, не самый точный способ, это очень простой способ, по крайней мере, сделать его чем-то правы. Он также превосходит locale в веб-приложении, поскольку locale не является потокобезопасным и устанавливает языковые настройки в масштабах всего процесса. Это также проще настроить, чем PyICU, который опирается на внешнюю библиотеку C.
I загрузил скрипт в github, поскольку оригинал был недоступен на момент написания этой статьи, и мне пришлось прибегнуть к веб-кэшам, чтобы получить его:
https://github.com/href/Python-Unicode-Collation-Algorithm
Я успешно использовал этот скрипт для разумной сортировки немецкого/французского / итальянского текста в модуле plone.
краткий и развернутый ответ:
locale.strcoll
под Python 2, иlocale.strxfrm
в самом деле решить эту проблему, и делает хорошую работу, предполагая, что у вас локаль в установленных вопрос. Я также тестировал его под Windows, где имена локалей смутно отличаются, но с другой стороны, похоже, что все локали, которые поддерживаются по умолчанию, установлены.
ICU
не обязательно делать это лучше на практике, однако это не так больше. В частности, он поддерживает сплиттеры, которые могут разбивать тексты на разных языках на слова. Это очень полезно для языков, которые не имеют разделителей слов. Вам нужно будет иметь корпус слов для использования в качестве основы для разделения, потому что это не входит, хотя.Он также имеет длинные имена для локалей, так что вы можете получить довольно отображаемые имена для локали, поддержка других календарей, чем григорианский (хотя я не уверен, что интерфейс Python поддерживает это) и тонн и тонны других более или менее неясных языковых поддержек.
в целом: если вы хотите сортировать в алфавитном порядке и в зависимости от локали, вы можете использовать
locale
модуль, если у вас нет особых требований или вам также нужна более зависимая от локали функциональность, например, разделитель слов.
Я вижу, что ответы уже сделали отличную работу, просто хотел указать на одну неэффективность кодирования в Человеческого Рода. Для применения выборочного Чара на чара перевод в строку Unicode с используется код:
spec_dict = {'Å':'A', 'Ä':'A'} def spec_order(s): return ''.join([spec_dict.get(ch, ch) for ch in s])
Python имеет гораздо лучший, более быстрый и более сжатый способ выполнения этой вспомогательной задачи (на строках Unicode-аналогичный метод для строк байтов имеет другую и несколько менее полезную спецификацию!- ):
spec_dict = dict((ord(k), spec_dict[k]) for k in spec_dict) def spec_order(s): return s.translate(spec_dict)
в дикт вы переходите к
translate
метод имеет Unicode ординалы (не строки) в качестве ключей, поэтому нам нужен этот шаг перестройки из исходного char-to-charspec_dict
. (Значения в dict вы проходите переводить [в отличие от ключей, которые должны быть порядковые номера, могут быть в Юникоде порядковые номера, произвольные строки в Юникоде, или нет, чтобы удалить соответствующий символ как часть перевода, так это просто указать "игнорировать определенного характера для целей сортировки", "карта ä АЭ на сортировке", а любить.)в Python 3 Вы можете получить шаг" перестройка " более просто, например:
spec_dict = ''.maketrans(spec_dict)
посмотреть документы для других способов, вы можете использовать этот
maketrans
статический метод в Python 3.
полное решение UCA
самый простой, легкий и простой способ сделать это, чтобы сделать выноску для модуля библиотеки Perl,Unicode::Collate:: Locale, который является подклассом стандартного Unicode:: Collate модуль. Все, что вам нужно сделать, это передать конструктору значение локали
"xv"
для Швеции.(вы можете не обязательно оценить это для шведского текста, но поскольку Perl использует абстрактные символы, вы можно использовать любую кодовую точку Unicode, которую вы хотите - независимо от платформы или сборки! Немногие языки предлагают такое удобство. Я упоминаю об этом, потому что в последнее время я много сражаюсь с Java за эту сумасшедшую проблему.)
проблема в том, что я не знаю, как получить доступ к модулю Perl из Python - apart, то есть с помощью выноски оболочки или двухсторонней трубы. С этой целью, поэтому я предоставил вам полный рабочий скрипт под названием ucsort что вы можете позвонить, чтобы сделать именно то, что вы попросили с совершенной легкостью.
этот скрипт на 100% соответствует полному Алгоритм Сортировки Юникода, со всеми вариантами пошива поддерживается!! И если у вас установлен дополнительный модуль или запущен Perl 5.13 или лучше, то у вас есть полный доступ к простым в использовании локалям CLDR. Увидеть ниже.
демонстрация
представьте, что входной набор упорядочен вот так:
b o i j n l m å y e v s k h d f g t ö r x p z a ä c u q
сортировка по умолчанию по кодовой точке дает:
a b c d e f g h i j k l m n o p q r s t u v x y z ä å ö
что неверно по всем правилам. Используя мой скрипт, который использует алгоритм сортировки Unicode, вы получаете такой порядок:
% perl ucsort /tmp/swedish_alphabet | fmt a å ä b c d e f g h i j k l m n o ö p q r s t u v x y z
это сортировка UCA по умолчанию. Чтобы получить шведский язык, позвоните ucsort таким образом:
% perl ucsort --locale=sv /tmp/swedish_alphabet | fmt a b c d e f g h i j k l m n o p q r s t u v x y z å ä ö
вот лучший вход демо. Во-первых, входной набор:
% fmt /tmp/swedish_set cTD cDD Cöd Cbd cAD cCD cYD Cud cZD Cod cBD Cnd cQD cFD Ced Cfd cOD cLD cXD Cid Cpd cID Cgd cVD cMD cÅD cGD Cqd Cäd cJD Cdd Ckd cÖD cÄD Ctd Czd Cxd cHD cND cKD Cvd Chd Cyd cUD Cld Cmd cED Crd Cad Cåd Ccd cRD cSD Csd Cjd cPD
код точки, это сортирует таким образом:
Cad Cbd Ccd Cdd Ced Cfd Cgd Chd Cid Cjd Ckd Cld Cmd Cnd Cod Cpd Cqd Crd Csd Ctd Cud Cvd Cxd Cyd Czd Cäd Cåd Cöd cAD cBD cCD cDD cED cFD cGD cHD cID cJD cKD cLD cMD cND cOD cPD cQD cRD cSD cTD cUD cVD cXD cYD cZD cÄD cÅD cÖD
но использование UCA по умолчанию делает его сортировку таким образом:
% ucsort /tmp/swedish_set | fmt cAD Cad cÅD Cåd cÄD Cäd cBD Cbd cCD Ccd cDD Cdd cED Ced cFD Cfd cGD Cgd cHD Chd cID Cid cJD Cjd cKD Ckd cLD Cld cMD Cmd cND Cnd cOD Cod cÖD Cöd cPD Cpd cQD Cqd cRD Crd cSD Csd cTD Ctd cUD Cud cVD Cvd cXD Cxd cYD Cyd cZD Czd
но в шведском языке, таким образом:
% ucsort --locale=sv /tmp/swedish_set | fmt cAD Cad cBD Cbd cCD Ccd cDD Cdd cED Ced cFD Cfd cGD Cgd cHD Chd cID Cid cJD Cjd cKD Ckd cLD Cld cMD Cmd cND Cnd cOD Cod cPD Cpd cQD Cqd cRD Crd cSD Csd cTD Ctd cUD Cud cVD Cvd cXD Cxd cYD Cyd cZD Czd cÅD Cåd cÄD Cäd cÖD Cöd
если вы предпочитаете сортировать в верхнем регистре перед Нижним, сделайте следующее:
% ucsort --upper-before-lower --locale=sv /tmp/swedish_set | fmt Cad cAD Cbd cBD Ccd cCD Cdd cDD Ced cED Cfd cFD Cgd cGD Chd cHD Cid cID Cjd cJD Ckd cKD Cld cLD Cmd cMD Cnd cND Cod cOD Cpd cPD Cqd cQD Crd cRD Csd cSD Ctd cTD Cud cUD Cvd cVD Cxd cXD Cyd cYD Czd cZD Cåd cÅD Cäd cÄD Cöd cÖD
Подгонянные Видов
вы можете сделать много других вещей с ucsort. Например, вот как сортировать заголовки на английском языке:
% ucsort --preprocess='s/^(an?|the)\s+//i' /tmp/titles Anathem The Book of Skulls A Civil Campaign The Claw of the Conciliator The Demolished Man Dune An Early Dawn The Faded Sun: Kesrith The Fall of Hyperion A Feast for Crows Flowers for Algernon The Forbidden Tower Foundation and Empire Foundation’s Edge The Goblin Reservation The High Crusade Jack of Shadows The Man in the High Castle The Ringworld Engineers The Robots of Dawn A Storm of Swords Stranger in a Strange Land There Will Be Time The White Dragon
вам понадобится Perl 5.10.1 или лучше запустить скрипт вообще. Для поддержки локали необходимо либо установить дополнительный модуль CPAN
Unicode::Collate::Locale
. Кроме того, вы можете установить версии разработки Perl, 5.13+, которые включают этот модуль стандартно.Соглашения О Вызове
это быстрый прототип, так ucsort в основном документально подтверждена ООН(der). Но это его краткий обзор того, какие переключатели / параметры он принимает по команде линия:
# standard options --help|? --man|m --debug|d # collator constructor options --backwards-levels=i --collation-level|level|l=i --katakana-before-hiragana --normalization|n=s --override-CJK=s --override-Hangul=s --preprocess|P=s --upper-before-lower|u --variable=s # program specific options --case-insensitive|insensitive|i --input-encoding|e=s --locale|L=s --paragraph|p --reverse-fields|last --reverse-output|r --right-to-left|reverse-input
да, ладно: это действительно список аргументов, который я использую для вызова
Getopt::Long
, но вы получаете идею. :)если вы можете выяснить, как вызвать модули библиотеки Perl из Python напрямую, не вызывая скрипт Perl, обязательно сделайте это. Я просто сам не знаю как. Я бы с удовольствием научился.
в то же время, я считаю, что этот скрипт будет делать то, что вам нужно сделать во всех ее конкретное - и многое другое! сейчас я использую это для всех сортировки текста. Это наконец-то делает то, что мне было нужно в течение долгого, долгого времени.
единственным недостатком является то, что
--locale
аргумент заставляет производительность идти по трубам, хотя это достаточно быстро для обычных, не-locale но все же 100% UCA совместимый сортировка. Поскольку он загружает все в память, вы, вероятно, не хотите использовать это в документах gigabyte. Я использую его много раз в день, и он уверен, что это здорово, имея вменяемую сортировку текста, наконец.
для его реализации вам нужно будет прочитать об " алгоритме сортировки Unicode" видеть http://en.wikipedia.org/wiki/Unicode_collation_algorithm
http://www.unicode.org/unicode/reports/tr10/
пример реализации здесь
http://jtauber.com/blog/2006/01/27/python_unicode_collation_algorithm/
в последнее время я использую zope.сайт ucol (https://pypi.python.org/pypi/zope.ucol) для этой задачи. Например, сортировка немецкого языка β:
>>> import zope.ucol >>> collator = zope.ucol.Collator("de-de") >>> mylist = [u"a", u'x', u'\u00DF'] >>> print mylist [u'a', u'x', u'\xdf'] >>> print sorted(mylist, key=collator.key) [u'a', u'\xdf', u'x']
zope.ucol также обертывает ICU, поэтому будет альтернативой PyICU.
Джефф Этвуд написал хороший пост на Естественный Порядок Сортировки, в нем он связан со скриптом, который делает в значительной степени то, что вы просите.
Это не тривиальный сценарий, во всяком случае, но он делает трюк.
Это далеко не полное решение для вашего случая использования, но вы можете взглянуть на unaccent.py скрипт из effbot.org.то, что он в основном делает, это удалить все акценты из текста. Вы можете использовать этот "санированный" текст для сортировки по алфавиту. (Для лучшего описания см. этой страница.)