如何在Python中按字母顺序sortingunicodestring?

Python默认按字节值sorting,这意味着é在z和其他同样有趣的事情之后。 什么是在Python中按字母顺序sorting的最佳方法?

有这样的图书馆吗? 我找不到任何东西。 优先select应该有语言支持,因此它理解åäö应该在瑞典语z之后sorting,但是ü应该按usorting等。因此Unicode支持几乎是一个要求。

如果没有图书馆,最好的办法是什么? 只需要从字母映射到整数值,并将string映射到一个整数列表?

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

更新 :在ICU和locale.strcoll之间sorting的核心区别是ICU使用完整的Unicodesortingalgorithm,而strcoll使用ISO 14651 。

这两个algorithm之间的区别在这里简要总结: http : //unicode.org/faq/collat​​ion.html#13 。 这些都是相当奇特的特例,在实践中应该很less有问题。

 >>> 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'] 

我没有看到答案。 我的应用程序按照使用python标准库的语言环境进行sorting。 这很容易。

 # 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) 

对Lennart和其他回答者的问题:没有人知道“locale”还是不符合这个任务?

试试James Tauber的Python Unicodesortingalgorithm 。 它可能不是完全按照你想要的,但似乎很值得一看。 有关这些问题的更多信息,请参阅Christopher Lenz的这篇文章 。

您可能也对pyuca感兴趣:

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

虽然这当然不是最准确的方法,但这至less是一个非常简单的方法。 它也在web应用程序中跳过语言环境,因为语言环境不是线程安全的,并在整个stream程范围内设置语言设置。 比依赖外部C库的PyICU更容易设置。

我把这个脚本上传到了github上,因为在写这篇文章的时候,原来这个脚本已经closures了,我不得不使用webcaching来获取它:

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

我成功地使用这个脚本来把德语/法语/意大利语的文本清理成plone模块。

一个总结和扩展的答案:

Python 2下的locale.strcolllocale.strxfrm将事实上解决问题,并且做得很好,假设你已经安装了有问题的语言环境。 我也在Windows下testing了它,其中语言环境名称容易混淆,但另一方面,它似乎默认安装了所有支持的语言环境。

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

它也有很长的语言环境名称,所以你可以得到漂亮的语言环境名称,支持其他日历,而不是格里高利(尽pipe我不确定Python接口是否支持这个function),吨和其他或多或less模糊的语言环境支持。

总而言之:如果你想按照字母顺序sorting和依赖于locale ,你可以使用locale模块,除非你有特殊的要求,或者还需要更多的语言环境相关的function,比如分词器。

我看到答案已经做得非常出色,只是想指出人类sorting中的一种编码效率低下问题。 要将select性字符逐字符转换应用于Unicodestrings,它将使用以下代码:

 spec_dict = {'Å':'A', 'Ä':'A'} def spec_order(s): return ''.join([spec_dict.get(ch, ch) for ch in s]) 

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

 spec_dict = dict((ord(k), spec_dict[k]) for k in spec_dict) def spec_order(s): return s.translate(spec_dict) 

你传递给translate方法的字典有Unicode序列(不是string)作为键,这就是为什么我们需要从原来的char-to-char spec_dict重build步骤。 (在传递字典中的值(相对于必须是序号的键),可以是Unicode序号,任意Unicodestring或None,以将相应的字符作为翻译的一部分,因此可以很容易地指定“忽略用于分类目的的特定字符“,”为了分类目的而将字符映射到ae“等)。

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

 spec_dict = ''.maketrans(spec_dict) 

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

完整的UCA解决scheme

最简单,最简单,最直接的方法就是将它作为标准Unicode :: Collat​​e模块的子类的Perl库模块Unicode :: Collat​​e :: Locale的标注。 所有你需要做的是传递给瑞典的构造函数一个"xv"的语言环境值。

(对于瑞典语的文本,你可能并不是非常感激,但是因为Perl使用了抽象字符,所以你可以使用任何Unicode代码点 – 不pipe是平台还是构build语言。最近在这个疯狂的问题上与Java失去了很多。

问题是,我不知道如何从Python访问Perl模块 – 除此之外,也就是使用shell标注或双面pipe道。 为此, 我已经为您提供了一个完整的工作脚本,称为ucsort ,您可以打电话完成您所要求的完全简单的工作。

该脚本100%符合完整的Unicodesortingalgorithm ,支持所有剪裁选项! 如果您安装了可选模块或运行Perl 5.13或更高版本,则可以完全访问易于使用的CLDR语言环境。 见下文。

示范

想象一下按照这种方式排列的input集:

 boijnlm å yevskhdfgt ö rxpza ä cuq 

按代码默认sorting产生:

 abcdefghijklmnopqrstu vxyz ä å ö 

这是每个人的书不正确。 使用我的脚本,它使用Unicodesortingalgorithm,你得到这个命令:

 % perl ucsort /tmp/swedish_alphabet | fmt a å ä bcdefghijklmno ö pqrstuvxyz 

这是默认的UCAsorting。 要获得瑞典地区,请通过以下方式联系ucsort

 % perl ucsort --locale=sv /tmp/swedish_alphabet | fmt abcdefghijklmnopqrstu vxyz å ä ö 

这里是一个更好的input演示。 首先,input集:

 % fmt /tmp/swedish_set cTD cDD Cöd Cbd cAD cCD cYD Cud cZD Cod cBD Cnd cQD cFD Ced Cfd cOD cLD cXD Cid Cpd cID Cgd cVD cMD cÅD cGD Cqd Cäd cJD Cdd Ckd cÖD cÄD Ctd Czd Cxd cHD cND cKD Cvd Chd Cyd cUD Cld Cmd cED Crd Cad Cåd Ccd cRD cSD Csd Cjd cPD 

通过代码点,这样sorting:

 Cad Cbd Ccd Cdd Ced Cfd Cgd Chd Cid Cjd Ckd Cld Cmd Cnd Cod Cpd Cqd Crd Csd Ctd Cud Cvd Cxd Cyd Czd Cäd Cåd Cöd cAD cBD cCD cDD cED cFD cGD cHD cID cJD cKD cLD cMD cND cOD cPD cQD cRD cSD cTD cUD cVD cXD cYD cZD cÄD cÅD cÖD 

但是使用默认的UCA可以这样sorting:

 % ucsort /tmp/swedish_set | fmt cAD Cad cÅD Cåd cÄD Cäd cBD Cbd cCD Ccd cDD Cdd cED Ced cFD Cfd cGD Cgd cHD Chd cID Cid cJD Cjd cKD Ckd cLD Cld cMD Cmd cND Cnd cOD Cod cÖD Cöd cPD Cpd cQD Cqd cRD Crd cSD Csd cTD Ctd cUD Cud cVD Cvd cXD Cxd cYD Cyd cZD Czd 

但在瑞典的语言环境,这样:

 % ucsort --locale=sv /tmp/swedish_set | fmt cAD Cad cBD Cbd cCD Ccd cDD Cdd cED Ced cFD Cfd cGD Cgd cHD Chd cID Cid cJD Cjd cKD Ckd cLD Cld cMD Cmd cND Cnd cOD Cod cPD Cpd cQD Cqd cRD Crd cSD Csd cTD Ctd cUD Cud cVD Cvd cXD Cxd cYD Cyd cZD Czd cÅD Cåd cÄD Cäd cÖD Cöd 

如果您希望大写在小写之前进行sorting,请执行以下操作:

 % ucsort --upper-before-lower --locale=sv /tmp/swedish_set | fmt Cad cAD Cbd cBD Ccd cCD Cdd cDD Ced cED Cfd cFD Cgd cGD Chd cHD Cid cID Cjd cJD Ckd cKD Cld cLD Cmd cMD Cnd cND Cod cOD Cpd cPD Cqd cQD Crd cRD Csd cSD Ctd cTD Cud cUD Cvd cVD Cxd cXD Cyd cYD Czd cZD Cåd cÅD Cäd cÄD Cöd cÖD 

自定义sorting

你可以用ucsort做很多其他的事情。 例如,以下是如何对英文标题进行sorting:

 % ucsort --preprocess='s/^(an?|the)\s+//i' /tmp/titles Anathem The Book of Skulls A Civil Campaign The Claw of the Conciliator The Demolished Man Dune An Early Dawn The Faded Sun: Kesrith The Fall of Hyperion A Feast for Crows Flowers for Algernon The Forbidden Tower Foundation and Empire Foundation's Edge The Goblin Reservation The High Crusade Jack of Shadows The Man in the High Castle The Ringworld Engineers The Robots of Dawn A Storm of Swords Stranger in a Strange Land There Will Be Time The White Dragon 

一般来说,您将需要Perl 5.10.1或更高版本来运行脚本。 对于语言环境支持,您必须安装可选的CPAN模块Unicode::Collate::Locale 。 或者,您可以安装标准包含该模块的Perl 5.13+开发版本。

呼叫约定

这是一个快速的原型,所以ucsort大部分是un(der)logging。 但是,这是它在命令行中接受什么开关/选项的概要:

  # standard options --help|? --man|m --debug|d # collator constructor options --backwards-levels=i --collation-level|level|l=i --katakana-before-hiragana --normalization|n=s --override-CJK=s --override-Hangul=s --preprocess|P=s --upper-before-lower|u --variable=s # program specific options --case-insensitive|insensitive|i --input-encoding|e=s --locale|L=s --paragraph|p --reverse-fields|last --reverse-output|r --right-to-left|reverse-input 

是的,好的:这实际上是我用来调用Getopt::Long的参数列表,但你明白了。 🙂

如果你可以直接调用Perl的Perl库模块而不用调用Perl脚本,那么一定要这么做。 我只是不知道自己如何。 我很想学习如何。

与此同时,我相信这个脚本将完成你所需要完成的工作, 甚至更多! 我现在用这个来进行所有的文本sorting。 它终于做了我需要很长很长的时间。

唯一的缺点是 – --locale参数会导致性能下降,尽pipe对于常规的非本地化但是仍然100%符合UCA的sorting来说足够快。 由于它将所有内容加载到内存中,因此您可能不希望在技嘉文档中使用此function。 我一天使用它很多次,而且它确实有很好的理智的文本分类。

最近我一直在使用zope.ucol( https://pypi.python.org/pypi/zope.ucol )来完成这个任务。 例如,sorting德国ß:

 >>> import zope.ucol >>> collator = zope.ucol.Collator("de-de") >>> mylist = [u"a", u'x', u'\u00DF'] >>> print mylist [u'a', u'x', u'\xdf'] >>> print sorted(mylist, key=collator.key) [u'a', u'\xdf', u'x'] 

zope.ucol也包装ICU,所以可以替代PyICU。

杰夫·阿特伍德(Jeff Atwood)在“ 自然sorting” ( Natural Sort Order)上写了一篇很好的文章。

这不是一个无足轻重的脚本,但它是有用的。

对于您的使用情况来说,这并不是一个完整的解决scheme,但您可以查看来自effbot.org的unaccent.py脚本。 它基本上是从文本中删除所有重音。 您可以使用“消毒”文本按字母顺序sorting。 (为了更好的描述,请参阅此页。)