У меня есть проблема с сортировкой списков с помощью unicode сопоставление в Python 2.5.1 и 2.6.5 на OSX, а также на Linux.
import locale
locale.setlocale(locale.LC_ALL, 'pl_PL.UTF-8')
print [i for i in sorted([u'a', u'z', u'ą'], cmp=locale.strcoll)]
Который должен распечатать:
[u'a', u'ą', u'z']
Но вместо этого распечатывает:
[u'a', u'z', u'ą']
При подведении его - выглядит, как будто strcoll был поврежден. Попробованный это различными типами переменных (fe. non-unicode закодированные строки).
Что я делаю неправильно?
С наилучшими пожеланиями, Tomasz Kopczuk.
По-видимому, единственный способ сортировки для работы на всех платформах - это использовать библиотеку ICU с привязками PyICU ( PyICU на PyPI ).
В OS X: sudo port install py26-pyicu
, помня об ошибке, описанной здесь: https://svn.macports.org/ticket/23429 (о радость использования macports).
К сожалению, документации по PyICU очень не хватает, но мне удалось выяснить, как это делается:
import PyICU
collator = PyICU.Collator.createInstance(PyICU.Locale('pl_PL.UTF-8'))
print [i for i in sorted([u'a', u'z', u'ą'], cmp=collator.compare)]
что дает:
[u'a', u'ą', u'z']
Еще одно преимущество - @bobince: он ориентирован на многопотоковое исполнение, поэтому не бесполезен при настройке локалей по запросу.
Просто добавлю к расследованию tkopczuk: это определенно ошибка gcc, по крайней мере, для версии 4.2.1 в OS X 10.6.4. Его можно воспроизвести, вызвав C strcoll ()
непосредственно как в этом фрагменте .
РЕДАКТИРОВАТЬ: Все еще в той же системе, я обнаружил, что для версий UTF-8 de_DE, fr_FR, pl_PL проблема существует, но для версий ISO-88591 fr_FR и de_DE порядок сортировки правильный. К сожалению для OP, ISO-88592 pl_PL также содержит ошибки:
The order for Polish ISO-8859 is:
LATIN SMALL LETTER A
LATIN SMALL LETTER Z
LATIN SMALL LETTER A WITH OGONEK
The LC_COLLATE culture and encoding settings were pl_PL, ISO8859-2.
The order for Polish Unicode is:
LATIN SMALL LETTER A
LATIN SMALL LETTER Z
LATIN SMALL LETTER A WITH OGONEK
The LC_COLLATE culture and encoding settings were pl_PL, UTF8.
The order for German Unicode is:
LATIN SMALL LETTER A
LATIN SMALL LETTER Z
LATIN SMALL LETTER A WITH DIAERESIS
The LC_COLLATE culture and encoding settings were de_DE, UTF8.
The order for German ISO-8859 is:
LATIN SMALL LETTER A
LATIN SMALL LETTER A WITH DIAERESIS
LATIN SMALL LETTER Z
The LC_COLLATE culture and encoding settings were de_DE, ISO8859-1.
The order for Fremch ISO-8859 is:
LATIN SMALL LETTER A
LATIN SMALL LETTER E WITH ACUTE
LATIN SMALL LETTER Z
The LC_COLLATE culture and encoding settings were fr_FR, ISO8859-1.
The order for French Unicode is:
LATIN SMALL LETTER A
LATIN SMALL LETTER Z
LATIN SMALL LETTER E WITH ACUTE
The LC_COLLATE culture and encoding settings were fr_FR, UTF8.
В ubuntu lucid сортировка с помощью cmp вроде работает нормально, но моя выходная кодировка неверна.
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'pl_PL.UTF-8')
'pl_PL.UTF-8'
>>> print [i for i in sorted([u'a', u'z', u'ą'], cmp=locale.strcoll)]
[u'a', u'\u0105', u'z']
Использование ключа с locale.strxfrm не работает, если я чего-то не упускаю
>>> print [i for i in sorted([u'a', u'z', u'ą'], key=locale.strxfrm)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u0105' in position 0: ordinal not in range(128)