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

2025-02-13 08:36:00
admin
原创
67
摘要:问题描述:Python 默认按字节值排序,这意味着 é 排在 z 后面,还有其他同样有趣的东西。在 Python 中按字母顺序排序的最佳方法是什么?有这样的库吗?我什么也没找到。排序最好有语言支持,这样它就能理解瑞典语中åäö 应该排在 z 之后,但 ü 应该排在 u 之后,等等。因此 Unicode 支持几...

问题描述:

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

有这样的库吗?我什么也没找到。排序最好有语言支持,这样它就能理解瑞典语中åäö 应该排在 z 之后,但 ü 应该排在 u 之后,等等。因此 Unicode 支持几乎是必需的。

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


解决方案 1:

IBM 的ICU库可以实现这一点(以及更多)。它具有 Python 绑定:PyICU。

更新:ICU 和 之间排序的核心区别locale.strcoll在于 ICU 使用完整的Unicode 排序算法,而strcoll使用ISO 14651。

这两种算法之间的差异简要总结如下: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']

解决方案 2:

我在答案中没有看到这一点。我的应用程序使用 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)

向 Lennart 和其他回答者提出的问题:没有人知道“locale”吗?或者它不能胜任这项任务?

解决方案 3:

您可能也对pyuca感兴趣:

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

虽然这肯定不是最精确的方法,但这是一种非常简单的方法,至少可以在一定程度上解决问题。它还胜过 web 应用程序中的 locale,因为 locale 不是线程安全的,并且会在整个进程范围内设置语言设置。它也比依赖外部 C 库的 PyICU 更容易设置。

我将脚本上传到了 github,因为在撰写本文时原始脚本已经关闭,因此我不得不借助网络缓存来获取它:

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

我成功地使用该脚本在 plone 模块中对德语/法语/意大利语文本进行了合理的排序。

解决方案 4:

尝试 James Tauber 的Python Unicode 排序算法。它可能不会完全满足您的要求,但值得一看。有关这些问题的更多信息,请参阅Christopher Lenz 的这篇文章。

解决方案 5:

摘要和扩展答案:

locale.strcoll在 Python 2 下,locale.strxfrm实际上可以解决问题,并且效果很好,前提是您已安装相关区域设置。我也在 Windows 下测试过,其中区域设置名称令人困惑地不同,但另一方面,它似乎默认安装了所有受支持的语言环境。

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

它还为语言环境提供了很长的名称,这样您就可以获得漂亮的语言环境显示名称,支持公历以外的其他日历(尽管我不确定 Python 接口是否支持这一点)以及大量其他或多或少晦涩难懂的语言环境支持。

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

解决方案 6:

我看到答案已经做得很好了,只是想指出Human Sort中的一个编码效率低下的问题。要对unicode字符串s应用选择性的逐字符转换,它使用以下代码:

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

def spec_order(s):
    return ''.join([spec_dict.get(ch, ch) for ch in s])

Python 有一种更好、更快、更简洁的方法来执行这个辅助任务(对于 Unicode 字符串——对于字节字符串的类似方法有一个不同且不太有用的规范!-):

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

def spec_order(s):
    return s.translate(spec_dict)

传递给该方法的字典translate以 Unicode 序数(而非字符串)作为键,这就是为什么我们需要从原始 char-to-char 重建步骤的原因spec_dict。(传递给翻译的字典中的值 [与键相反,键必须是序数] 可以是 Unicode 序数、任意 Unicode 字符串或 None 以在翻译过程中删除相应的字符,因此很容易指定“为了排序而忽略某个字符”、“为了排序而将 ä 映射到 ae”等)。

在 Python 3 中,您可以更简单地执行“重建”步骤,例如:

spec_dict = ''.maketrans(spec_dict)

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

解决方案 7:

完整的 UCA 解决方案

最简单、最轻松、最直接的方法是调用 Perl 库模块Unicode::Collat​​e::Locale,它是标准Unicode::Collat​​e模块的子类。您需要做的就是向构造函数传递"xv"瑞典的语言环境值。

(对于瑞典语文本,您可能不一定会喜欢这一点,但是由于 Perl 使用抽象字符,因此您可以使用任何您喜欢的 Unicode 代码点 — 无论平台或构建如何!很少有语言能提供这样的便利。我提到这一点是因为我最近一直在与 Java 就这个令人抓狂的问题进行苦战,但都以失败告终。)

问题是我不知道如何从 Python 访问 Perl 模块 — 除了使用 shell 调用或双向管道。为此,我为您提供了一个完整的工作脚本,名为ucsort,您可以调用它来非常轻松地完成您的要求。

此脚本 100% 符合完整的Unicode 排序算法,并支持所有定制选项!!如果您安装了可选模块或运行 Perl 5.13 或更高版本,那么您就可以完全访问易于使用的 CLDR 语言环境。见下文。

示范

想象一个按以下方式排序的输入集:

b o i j n l m å y e v s k h d f g t ö r x p z a ä c u q

默认按代码点排序的结果为:

a b c d e f g h i j k l m n o p q r s t u v x y z ä å ö

这与每个人的观点都不符。使用我的脚本(使用 Unicode 排序算法),您将获得以下顺序:

% perl ucsort /tmp/swedish_alphabet | fmt
a å ä b c d e f g h i j k l m n o ö p q r s t u v x y z

这是默认的 UCA 排序。要获取瑞典语言环境,请按如下方式调用ucsort

% perl ucsort --locale=sv /tmp/swedish_alphabet | fmt
a b c d e f g h i j k l m n o p q r s t u v x y z å ä ö

下面是一个更好的输入演示。首先,输入集:

% 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

根据代码点,排序如下:

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 会使其按以下方式排序:

% 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

如果您希望大写字母先于小写字母排序,请执行以下操作:

% 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

定制排序

您还可以使用ucsort做很多其他事情。例如,以下是如何对英文标题进行排序:

% 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基本没有文档记录。但这是它在命令行上接受的开关/选项的概要:

    # 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,但你明白我的意思了。:)

如果您能弄清楚如何直接从 Python 调用 Perl 库模块而不调用 Perl 脚本,请务必这样做。我自己不知道怎么做。我很想学习如何做。

与此同时,我相信这个脚本将满足您的所有需求 —甚至更多! 我现在使用它来进行所有文本排序。它终于满足了我长久以来的需要。

唯一的缺点是该--locale参数会导致性能下降,尽管它对于常规、非本地化但仍 100% 符合 UCA 的排序来说已经足够快了。由于它将所有内容加载到内存中,因此您可能不想在 GB 文档上使用它。我每天使用它很多次,最终获得合理的文本排序确实很棒。

解决方案 8:

要实现它,您需要阅读有关“Unicode 排序算法”的内容,请参阅
http://en.wikipedia.org/wiki/Unicode_collat ​​ion_algorithm

http://www.unicode.org/unicode/reports/tr10/

示例实现在这里

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

解决方案 9:

最近我一直在使用 zope.ucol ( https://pypi.python.org/pypi/zope.ucol ) 来完成这项任务。例如,对德语 ß 进行排序:

>>> 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 的替代品。

解决方案 10:

它远非您用例的完整解决方案,但您可以查看effbot.org 上的unaccent.py脚本。它基本上的作用是从文本中删除所有重音符号。您可以使用该“净化”文本按字母顺序排序。(有关更详细的描述,请参阅此页面。)

解决方案 11:

Jeff Atwood 写了一篇关于自然排序顺序的很好的文章,其中他链接到一个脚本,该脚本基本上可以完成你所要求的操作。

无论如何,这不是一个简单的脚本,但是它确实起了作用。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1989  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1446  
  在当今快速发展的IT行业中,项目管理工具的选择对于项目的成功至关重要。随着技术的不断进步,项目经理们需要更加高效、灵活的工具来应对复杂的项目需求。本文将介绍2025年IT项目经理力推的10款管理工具,帮助您在项目管理中取得更好的成果。信创国产项目管理软件 - 禅道禅道是一款国产开源的项目管理软件,禅道开源版不限人数,功...
项目管理工具   0  
  在当今快速变化的商业环境中,项目管理软件已成为企业提升效率、优化资源分配和确保项目成功的关键工具。随着技术的不断进步,市场上涌现出众多功能各异的项目管理工具,每一款都有其独特的优势和适用场景。本文将深入评测2025年最受欢迎的10款项目管理软件,帮助您根据自身需求做出明智的选择。信创国产项目管理软件 - 禅道禅道是一款...
项目管理平台   2  
  产品开发效率对于企业的竞争力至关重要。在当今复杂多变的商业环境中,如何有效提升产品开发效率成为众多企业关注的焦点。产品生命周期管理(PLM)作为一种整合产品全生命周期信息的管理理念和技术,为提升产品开发效率提供了有力的支持。通过合理运用PLM,企业能够优化流程、加强协作、提高数据管理水平,从而实现产品开发的高效运作。接...
plm开发流程软件   3  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用