Python 无法正确排序 unicode。 Strcoll 没有帮助
我在 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)]
应该打印:
[u'a', u'ą', u'z']
但是却打印出:
[u'a', u'z', u'ą']
总结一下 - 看起来 strcoll 好像被破坏了。尝试使用各种类型的变量(例如非 unicode 编码的字符串)。
我做错了什么?
此致, 托马斯·科普丘克。
I've got a problem with sorting lists using unicode collation in Python 2.5.1 and 2.6.5 on OSX, as well as on 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)]
Which should print:
[u'a', u'ą', u'z']
But instead prints out:
[u'a', u'z', u'ą']
Summing it up - it looks as if strcoll was broken. Tried it with various types of variables (fe. non-unicode encoded strings).
What do I do wrong?
Best regards,
Tomasz Kopczuk.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
显然,排序在所有平台上工作的唯一方法是使用带有 PyICU 绑定的 ICU 库 (PyICU在 PyPI 上)。
在 OS X 上:
sudo port install py26-pyicu
,注意此处描述的错误:https ://svn.macports.org/ticket/23429(哦,使用 macports 的乐趣)。不幸的是,PyICUs 文档严重缺乏,但我设法找出它是如何完成的:
这给出了:
另一个优点 - @bobince:它是线程安全的,因此在设置请求明智的语言环境时并非无用。
Apparently, the only way for sorting to work on all platforms is to use the ICU library with PyICU bindings (PyICU on PyPI).
On OS X:
sudo port install py26-pyicu
, minding bug described here: https://svn.macports.org/ticket/23429 (oh the joy of using macports).PyICUs documentation is unfortunately severely lacking, but I managed to find out how it's done:
which gives:
Another pro - @bobince: it's thread-safe, so not useless when setting request-wise locales.
只是为了补充 tkopczuk 的调查:这绝对是一个 gcc bug,至少对于 OS X 10.6.4 上的版本 4.2.1 来说是这样。可以通过直接调用 C
strcoll()
来重现它,就像此代码段中的 一样。编辑:仍然在同一系统上,我发现对于 UTF-8 版本的 de_DE、fr_FR、pl_PL,问题确实存在,但对于 ISO-88591 版本的 fr_FR 和 de_DE,排序顺序是正确的。不幸的是,对于OP来说,ISO-88592 pl_PL也有错误:
Just to add to tkopczuk's investigation: This is definitely a gcc bug, at least for version 4.2.1 on OS X 10.6.4. It can be reproduced by calling C
strcoll()
directly as in this snippet.EDIT: Still on the same system, I find that for the UTF-8 versions of de_DE, fr_FR, pl_PL, the problem is there, but for the ISO-88591 versions of fr_FR and de_DE, sort order is correct. Unfortunately for the OP, ISO-88592 pl_PL is also buggy:
以下是我如何正确排序波斯语(没有 PyICU)(使用 python 3.x):
首先设置语言环境(不要忘记导入语言环境和平台 )
然后使用键排序:
对于对象列表:
最后您可以返回区域设置:
Here is how i managed to sort Persian language correctly (without PyICU)(using python 3.x):
First set the locale (don't forget to import locale and platform)
Then sort using key:
For list of Objects:
Finally you can return the locale:
@gnibbler,使用 PyICU 和 sorted() 函数确实可以在 Python3 环境中工作。经过一番深入研究 ICU API 文档和一些实验后,我发现了 getSortKey() 函数:
它生成所需的排序规则:
而不是不需要的排序规则:
@gnibbler, using PyICU with the sorted() function does work in a Python3 Environment. After a little digging through the ICU API documentation and some experimentation, I came across the getSortKey() function:
which produces the desired collation:
instead of the undesired collation:
(参考:http://docs.python.org/3.3/library/functools.html )
(Ref.: http://docs.python.org/3.3/library/functools.html)
自 2012 年以来,出现了一个库
natsort
。它包括令人惊叹的功能,例如natsorted
和humansorted
。更重要的是,它们不仅适用于列表!。代码:输出:
正如您所看到的,对字典进行排序时结果有所不同,但考虑到给定的列表,两个结果都是正确的。
顺便说一句,这个库也非常适合对包含数字的字符串进行排序:
输出:
Since 2012 there's been a library
natsort
. It includes amazing functions such asnatsorted
andhumansorted
. More importantly, they work not only with lists!. Code:Output:
As you can see results differ when sorting dictionaries but considering given list both results are correct.
By the way, this library is also great to sort strings containing numbers:
Output:
在 ubuntu lucid 上,使用 cmp 进行排序似乎工作正常,但我的输出编码是错误的。
将 key 与 locale.strxfrm 结合使用不起作用,除非我丢失了某些东西
On ubuntu lucid the sorting with cmp seems to work ok, but my output encoding is wrong.
Using key with locale.strxfrm does not work unless I am missing something
这是一个老问题,但需要澄清一些。对于 Python 中的区域设置敏感排序,有两种方法可用。您采用哪种方法取决于您使用的操作系统。
第一种方法是使用内置的 locale 模块。这取决于您使用的操作系统以及可用的区域设置。
如果我使用的是使用 glibc 的 Linux 版本,我将得到
['a', 'ą', 'z']
。如果我使用的是使用 Musl libc 的 Linux 版本,或者是为嵌入式系统开发的 Linux 发行版,我将得到
['a', 'z', 'ą']
,即区域设置敏感排序是不支持。如果我使用基于 BSD libc 的系统(例如 macOS),我将得到
['a', 'z', 'ą']
。在 macOS 上,如果运行以下命令:
您将得到
/usr/share/locale/pl_PL/LC_COLLATE -> ../la_LN.US-ASCII/LC_COLLATE
,即波兰语排序规则表符号链接到另一个排序规则表,创建语言不敏感的排序。这与其他 BSD libc 派生系统类似,其中优先考虑文件系统中稳定的区域设置独立排序。对于安装了 icu4c 的系统,第二种方法是使用 PyICU。 ICU4C 使用通用区域设置数据存储库 (CLDR)。 CLDR 语言环境数据比基于 libc 的实现中的语言环境数据更广泛。
给出
['a', 'ą', 'z']
。区域设置数据因实现而异,这不会影响排序,但也可以在其他区域设置敏感操作中看到。
An old question, but some clarifications are required. For locale sensitive sorting in Python, two approaches are available. Which approach you take, depends on what operating system you are using.
First approach is to use the in-built
locale
module. This will depend on what operating system you are on, and what locales are available.If I am using a version of Linux using glibc, I will get
['a', 'ą', 'z']
.If I am using a version of Linux using Musl libc, or a Linux distro developed for embedded systems, I will get
['a', 'z', 'ą']
, i.e. locale sensitive sorting is unsupported.If I am using a system based on BSD libc (like macOS), I will get
['a', 'z', 'ą']
.On macOS, if you run the following command:
you get
/usr/share/locale/pl_PL/LC_COLLATE -> ../la_LN.US-ASCII/LC_COLLATE
, i.e. The Polish collation table is symlinked to another collation table, creating a language insensitive sort. This is similar to other BSD libc derived system, where priority was given to stable locale independent sorting in the filesystem.The second approach, for systems with icu4c installed, is to use PyICU. ICU4C uses the Common Locale Data Repository (CLDR). CLDR locale data is more extensive than locale data in libc based implementations.
Which gives
['a', 'ą', 'z']
.Locale data varies across implementations, this just doesn't affect sorting, but can be seen in other locale sensitive operations as well.