Python, не сортирующий unicode правильно. Strcoll не помогает

У меня есть проблема с сортировкой списков с помощью 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.

21
задан Tomek Kopczuk 5 August 2010 в 08:25
поделиться

3 ответа

По-видимому, единственный способ сортировки для работы на всех платформах - это использовать библиотеку 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: он ориентирован на многопотоковое исполнение, поэтому не бесполезен при настройке локалей по запросу.

18
ответ дан 29 November 2019 в 21:12
поделиться

Просто добавлю к расследованию 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.
4
ответ дан 29 November 2019 в 21:12
поделиться

В 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)
0
ответ дан 29 November 2019 в 21:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: