使用locale/collation对字典按键进行排序

12
以下代码忽略了语言环境,使得Égypt排在最后,有什么问题吗?
dict = {"United States": "United States", "Spain" : "Spain", "England": "England", "Égypt": "Égypt"}

import locale

# using your default locale (user settings)
locale.setlocale(locale.LC_ALL,"fr_FR")
print OrderedDict(sorted(dict.items(), key=lambda t: t[0], cmp=locale.strcoll))

这是输出结果:
OrderedDict([('England', 'England'), ('Spain', 'Spain'), ('United States', 'United States'), ('\xc3\x89gypt', '\xc3\x89gypt')])

1
我认为您不能同时指定 keycmp - Daniel Roseman
@Daniel其实你可以这样做……只是这样做有点奇怪(键的结果最终被传递给cmp函数)。 - Jon Clements
иҝҷйҮҢжңҖеӨ§зҡ„й—®йўҳжҳҜдёҚжё…жҘҡlocaleеҜ№дәҺfr_FRдјҡе°ҠйҮҚе“Әз§Қзј–з ҒгҖӮ - Martijn Pieters
3
因此,结论是这篇文章是 Python not sorting unicode properly. Strcoll doesn't help 的重复,以及其他提到 PyICU 的帖子,因为这是解决这个问题的正确答案。 - Martijn Pieters
将你的代码复制粘贴到我的Python 2.7中,得到了正确的答案。 - Tigran Saluev
显示剩余3条评论
2个回答

2
考虑以下内容...
import unicodedata
from collections import OrderedDict
dict = {"United States": "United States", "Spain" : "Spain", "England": "England", "Égypt": "Égypt"}

import locale

# using your default locale (user settings)
locale.setlocale(locale.LC_ALL,"fr_FR")

print OrderedDict(sorted(dict.items(),cmp= lambda a,b: locale.strcoll(unicodedata.normalize('NFD', unicode(a)[0]).encode('ASCII', 'ignore'),
                                                                       unicodedata.normalize('NFD', unicode(b)[0]).encode('ASCII', 'ignore'))))

一定有比写大量代码来更改语言环境的更好的解决方案。 - imrek
还应该注意,设置区域设置可能会影响Python实例的其他部分。 - Marcel Wilson
注意:在Python 3中,排序函数不再具有“cmp”参数,它们只有“key”。您可以使用“locale.strxfrm”作为键来获得与“locale.strcoll”相同的结果。 - Sebastian Riese
2
注意2:警告更改区域设置是程序的全局状态,可能会导致意外行为(在库代码中永远不应该这样做)。 - Sebastian Riese

-1

这里有一个解决方法。

使用Unicode的规范分解形式http://en.wikipedia.org/wiki/Unicode_equivalence#Normal_forms

# utf-8 <-> unicode is left as exercise to the reader
egypt = unicodedata.normalize("NFD", egypt)

sorted(['Egypt', 'E\xcc\x81gypt', 'US'])
['Egypt', 'E\xcc\x81gypt', 'US']

这实际上并没有考虑到区域设置。

除此之外,尝试使用更新的Python(是的,我知道)或来自Martijn链接问题和相应答案的ICU库。


这并不能解决问题,因为对于许多字符串它将导致错误的排序,例如:>>> sorted(["Égypt", "Example"], key=lambda x: unicodedata.normalize('NFD', x)) ['Example', 'Égypt'] - Sebastian Riese

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接