如何在Python中按字母顺序对unicode字符串进行排序?

Len*_*bro 94 python sorting unicode collation internationalization

Python默认按字节值排序,这意味着é来自z和其他同样有趣的东西.在Python中按字母顺序排序的最佳方法是什么?

有这个图书馆吗?我找不到任何东西.最好排序应该有语言支持所以它理解åäö应该用瑞典语中的z排序,但是ü应该用u等排序.因此,Unicode支持是非常必要的.

如果没有库,那么最好的方法是什么?只需从字母到整数值进行映射,然后将字符串映射到整数列表即可?

Raf*_*ird 70

IBM的ICU库可以做到这一点(还有更多).它有Python绑定:PyICU.

更新:ICU之间排序的核心差异locale.strcoll是ICU 在使用ISO 14651时使用完整的Unicode排序算法.strcoll

这两种算法之间的差异简要总结如下:http://unicode.org/faq/collat​​ion.html#13.这些是相当奇特的特殊情况,在实践中应该很少.

>>> import icu # pip install PyICU
>>> sorted(['a','b','c','ä'])
['a', 'b', 'c', 'ä']
>>> collator = icu.Collator.createInstance(icu.Locale('de_DE.UTF-8'))
>>> sorted(['a','b','c','ä'], key=collator.getSortKey)
['a', 'ä', 'b', 'c']
Run Code Online (Sandbox Code Playgroud)


u0b*_*6ae 52

我在答案中没有看到这一点.我的应用程序使用python的标准库根据语言环境进行排序.这很容易.

# python2.5 code below
# corpus is our unicode() strings collection as a list
corpus = [u"Art", u"Älg", u"Ved", u"Wasa"]

import locale
# this reads the environment and inits the right locale
locale.setlocale(locale.LC_ALL, "")
# alternatively, (but it's bad to hardcode)
# locale.setlocale(locale.LC_ALL, "sv_SE.UTF-8")

corpus.sort(cmp=locale.strcoll)

# in python2.x, locale.strxfrm is broken and does not work for unicode strings
# in python3.x however:
# corpus.sort(key=locale.strxfrm)
Run Code Online (Sandbox Code Playgroud)

Lennart和其他回答者的问题:没有人知道'locale'或者不能完成这项任务吗?

  • 顺便说一下2)语言环境模块只适用于您生成的语言环境(对于Linux框),而不适用于任何任意语言环境."locale -a"会告诉你哪个 (6认同)
  • @Georg:我相信locale只支持一个简单的substring-> collat​​ing_element映射.它不处理像扩展(æ排序为"ae"),法语口音排序(字母从左到右排序,但是从右到左的重音),重新排列以及可能还有更多的东西.详细信息(完整的UCA功能集):http://unicode.org/reports/tr10/和here(locale collat​​ion):http://www.chm.tu-dresden.de/edv/manuals/aix/files/ aixfiles/LC_COLLATE.htm (6认同)
  • 这里最大的问题是:您必须为整个应用程序全局设置区域设置。– 您不能仅仅将其用于手头的比较。 (3认同)
  • 要明确回答这个问题:是的,*是*可以胜任这项任务.显然有一些特殊情况,完整的Unicode排序算法处理得更好,但除非你已经知道你不会注意到的机会. (2认同)

Vin*_*jip 9

试试James Tauber的Python Unicode校对算法.它可能不会完全按照您的意愿完成,但似乎值得一看.有关这些问题的更多信息,请参阅Christopher Lenz的这篇文章.


hre*_*ef_ 8

您可能也对pyuca感兴趣:

http://jtauber.com/blog/2006/01/27/python_unicode_collat​​ion_algorithm/

虽然它肯定不是最精确的方式,但它是一种非常简单的方法,至少可以让它有点正确.它还在webapp中击败语言环境,因为语言环境不是线程安全的,并在进程范围内设置语言设置.它比PyICU更容易设置,PyICU依赖于外部C库.

我将脚本上传到github,因为在撰写本文时原文已经关闭了,我不得不使用Web缓存来获取它:

https://github.com/href/Python-Unicode-Collat​​ion-Algorithm

我成功地使用这个脚本在plone模块中巧妙地对德语/法语/意大利语文本进行排序.


Len*_*bro 7

摘要和扩展答案:

locale.strcoll在Python 2下,并且locale.strxfrm实际上将解决问题,并且做得很好,假设你安装了有问题的语言环境.我也在Windows下对它进行了测试,其中区域设置名称容易混淆,但另一方面,它似乎默认安装了所有支持的语言环境.

ICU在实践中并不一定能做得更好,但它会做得更多.最值得注意的是,它支持分割器,可以将不同语言的文本分成单词.这对于没有单词分隔符的语言非常有用.你需要有一个单词语料库作为分裂的基础,因为它不包括在内.

它还具有很长的语言环境名称,因此您可以获得该语言环境的漂亮显示名称,支持除Gregorian之外的其他日历(虽然我不确定Python界面是否支持)以及大量其他或多或少不明显的语言环境支持.

总而言之:如果要按字母顺序排序并依赖于语言环境,则可以使用该locale模块,除非您有特殊要求,或者还需要更多与语言环境相关的功能,如单词分割器.


Ale*_*lli 6

我看到答案已经做得很好,只是想指出人类排序中的一个编码效率低下.要将选择性char-by-char转换应用于unicode字符串s,它将使用以下代码:

spec_dict = {'Å':'A', 'Ä':'A'}

def spec_order(s):
    return ''.join([spec_dict.get(ch, ch) for ch in s])
Run Code Online (Sandbox Code Playgroud)

Python有一个更好,更快,更简洁的方式来执行这个辅助任务(在Unicode字符串上 - 字节字符串的类似方法有一个不同的,有点不太有用的规范! - ):

spec_dict = dict((ord(k), spec_dict[k]) for k in spec_dict)

def spec_order(s):
    return s.translate(spec_dict)
Run Code Online (Sandbox Code Playgroud)

传递给translate方法的字典有Unicode序数(不是字符串)作为键,这就是我们需要从原始char-to-char重建步骤的原因spec_dict.(您传递给翻译的字典中的值[与键相对,必须是序数]可以是Unicode序号,任意Unicode字符串或无以删除相应字符作为翻译的一部分,因此很容易指定"忽略"用于分类目的的某些字符","将ä映射到ae以用于分类目的"等.

在Python 3中,您可以更简单地获得"重建"步骤,例如:

spec_dict = ''.maketrans(spec_dict)
Run Code Online (Sandbox Code Playgroud)

有关在Python 3中使用此静态方法的其他方法,请参阅文档maketrans.