Python没有正确排序unicode.Strcoll没有帮助

Tom*_*zuk 21 python unicode locale

我在OSX上以及Linux上使用Python 2.5.1和2.6.5中的unicode排序对排序列表有问题.

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)]
Run Code Online (Sandbox Code Playgroud)

哪个应该打印:

[u'a', u'?', u'z']
Run Code Online (Sandbox Code Playgroud)

而是打印出来:

[u'a', u'z', u'?']
Run Code Online (Sandbox Code Playgroud)

总结一下 - 看起来好像strcoll坏了.尝试使用各种类型的变量(fe.非unicode编码的字符串).

我做错了什么?

此致,Tomasz Kopczuk.

Tom*_*zuk 18

显然,排序在所有平台上工作的唯一方法是使用带有PyICU绑定的ICU库(PyPI上的PyICU).

在操作系统X上:sudo port install py26-pyicu,这里描述的minding bug:https://svn.macports.org/ticket/23429(哦使用macports的乐趣).

不幸的是,PyICUs文档严重缺乏,但我设法找出它是如何完成的:

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)]
Run Code Online (Sandbox Code Playgroud)

这使:

[u'a', u'?', u'z']
Run Code Online (Sandbox Code Playgroud)

另一个亲@bobince:它是线程安全的,所以在设置请求方式的语言环境时没有用处.

  • 好的问题和良好的答案 - 你只需几步就可以领先于所有人,难怪你是否在波兰:).无论如何,这是我第二次看到Python的问题,它依赖于底层的C库.你知道这些可以提到哪里吗? (2认同)
  • 我同意.我做了一个Gist http://gist.github.com/509520,并会给几个人试用.我喜欢*i18n,但这些错误让它变得单调乏味. (2认同)

chr*_*yss 5

只是为了补充 tkopczuk 的调查:这绝对是一个 gcc 错误,至少对于 OS X 10.6.4 上的版本 4.2.1。它可以通过strcoll()直接调用 C 来复制,就像在这个片段中一样

编辑:仍然在同一个系统上,我发现对于 UTF-8 版本的 de_DE、fr_FR、pl_PL,问题就在那里,但对于 fr_FR 和 de_DE 的 ISO-88591 版本,排序顺序是正确的。不幸的是,对于 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.
Run Code Online (Sandbox Code Playgroud)


小智 5

这是我设法正确地对波斯语言进行排序的方法(没有PyICU)(使用python 3.x):

首先设置语言环境(别忘了导入语言环境平台

if platform.system() == 'Linux':
    locale.setlocale(locale.LC_ALL, 'fa_IR.UTF-8')
elif platform.system() == 'Windows':
   locale.setlocale(locale.LC_ALL, 'Persian_Iran.1256')
else:
   pass (or any other OS)
Run Code Online (Sandbox Code Playgroud)

然后使用键进行排序:

a = ['?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?']

print(sorted(a,key=locale.strxfrm))
Run Code Online (Sandbox Code Playgroud)

对于对象列表:

a = [{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"},{'id':"?"}]

print(sorted(a, key=lambda x: locale.strxfrm(x['id']))
Run Code Online (Sandbox Code Playgroud)

最后,您可以返回语言环境:

locale.setlocale(locale.LC_ALL, '')
Run Code Online (Sandbox Code Playgroud)