完整的 UCA 解决方案
最简单、最简单、最直接的方法是调用 Perl 库模块 Unicode::Collate::Locale,它是标准 Unicode::Collate 模块的子类。您需要做的就是向构造函数传递瑞典的语言环境值"xv"。
(对于瑞典语文本,您可能不一定喜欢这一点,但由于 Perl 使用抽象字符,您可以使用任何您喜欢的 Unicode 代码点——无论平台或构建!很少有语言提供这样的便利。我提到它是因为我最近在这个令人抓狂的问题上与 Java 进行了多次失败的战斗。)
问题是我不知道如何从 Python 访问 Perl 模块——除了使用 shell 标注或双面管道。为此,您可以致电I have therefore provided you with a complete working script called ucsort,轻松完成您所要求的工作。
此脚本 100% 符合完整的 Unicode Collation Algorithm,支持所有定制选项!!如果您安装了可选模块或运行 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 大多没有(der)记录在案。但这是它在命令行上接受的开关/选项的概要:
# 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 脚本的情况下直接从 Python 调用 Perl 库模块,那么一定要这样做。我只是不知道自己怎么样。我很想知道怎么做。
同时,我相信这个脚本会做你需要做的所有事情——还有更多!我现在将它用于所有的文本排序。它终于完成了我长期以来需要的工作。
唯一的缺点是 --locale 参数会导致性能下降,尽管它对于常规的非语言环境但仍然 100% 符合 UCA 排序已经足够快了。由于它将所有内容加载到内存中,您可能不想在千兆字节文档上使用它。我每天使用它很多次,最后对文本进行合理的排序肯定很棒。