代码之家  ›  专栏  ›  技术社区  ›  Lennart Regebro

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

  •  90
  • Lennart Regebro  · 技术社区  · 15 年前

    这里有图书馆吗?我什么也找不到。优先排序应该有语言支持,这样它就可以理解在瑞典语中·应该在z之后排序,但应该按u等排序。因此,Unicode支持几乎是一个要求。

    11 回复  |  直到 14 年前
        1
  •  76
  •   jfs    10 年前

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

    使现代化 locale.strcoll 是重症监护室用的全套 Unicode Collation Algorithm strcoll 使用 ISO 14651 .

    http://unicode.org/faq/collation.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
  •  58
  •   u0b34a0f6ae    15 年前

    我在答案中看不到这一点。我的应用程序使用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和其他回答者提出的问题:难道没有人知道“语言环境”吗?或者它不适合这个任务吗?

        3
  •  9
  •   Vinay Sajip    15 年前

    试试詹姆斯·陶伯的 Python Unicode Collation Algorithm this post 克里斯托弗·伦茨。

        4
  •  8
  •   Lennart Regebro    14 年前

    摘要和扩展答案:

    locale.strcoll 在Python2下,以及 locale.strxfrm 事实上,如果您安装了有问题的区域设置,它将解决问题,并且做得很好。我也在Windows下对它进行了测试,在Windows下,语言环境名称很不一样,但另一方面,它似乎安装了默认支持的所有语言环境。

    ICU 在实践中不一定做得更好,但它确实是这样做的 更多

    它还有很长的区域设置名称,因此您可以获得区域设置的漂亮显示名称、对Gregorian以外的其他日历的支持(尽管我不确定Python接口是否支持),以及大量其他或多或少不太清楚的区域设置支持。

    如果要按字母顺序和区域设置进行排序,可以使用 locale 模块,除非您有特殊要求,或者还需要更多依赖于区域设置的功能,如Word splitter。

        5
  •  8
  •   href_    13 年前

    皮卡 :

    http://jtauber.com/blog/2006/01/27/python_unicode_collation_algorithm/

    我将脚本上传到github,因为在撰写本文时,原始脚本已关闭,我不得不求助于web缓存来获取它:

    https://github.com/href/Python-Unicode-Collation-Algorithm

        6
  •  6
  •   Alex Martelli    15 年前

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

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

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

    你传给老师的口述 translate spec_dict . (您传递给翻译的dict中的值[与键相反,键必须是序数]可以是Unicode序数、任意Unicode字符串,也可以是无,以删除作为翻译一部分的相应字符,因此很容易指定“忽略某个字符进行排序”、“映射到ae进行排序”等)。

    spec_dict = ''.maketrans(spec_dict)
    

    看见 the docs 对于其他方法,您可以使用此 maketrans Python3中的静态方法。

        8
  •  1
  •   Brian Sutherland    11 年前

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

        9
  •  1
  •   M Somerville    8 年前

    完整的UCA解决方案

    最简单、最简单、最直接的方法是调用Perl库模块, Unicode::Collate::Locale ,这是标准的一个子类 Unicode::Collate "xv" 瑞典。

    (对于瑞典语文本,您可能不一定会喜欢这一点,但因为Perl使用抽象字符,所以无论平台或构建,您都可以使用任何Unicode代码点!很少有语言提供这种便利。我提到这一点是因为我最近在这一令人恼火的问题上与Java进行了一场失败的斗争。)

    I have therefore provided you with a complete working script called ucsort 你可以打电话完全按照你的要求轻松地完成。

    Unicode Collation Algorithm ,支持所有剪裁选项!!如果安装了可选模块或运行Perl5.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 --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
    

    一般来说,运行脚本需要Perl5.10.1或更高版本。对于区域设置支持,您必须安装可选的CPAN模块 Unicode::Collate::Locale

    呼叫约定

    乌索特 大部分是未(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 ,但你明白了。:)

    如果您能够弄清楚如何直接从Python调用Perl库模块而不调用Perl脚本,那么一定要这样做。我只是不知道我自己是怎么想的。我很想知道怎么做。

    同时,我相信这个脚本会做你需要做的事情 我现在将其用于所有文本排序。信息技术 最后 做我需要很久很久的事。

    --locale 参数会导致性能下降,尽管对于常规的非语言环境来说,其速度足够快 但仍然100%符合UCA 分类。因为它加载内存中的所有内容,所以您可能不想在千兆字节文档上使用它。我一天使用它很多次,而且它肯定最终有了一个合理的文本排序。

        10
  •  0
  •   Mark van Lent    14 年前

    对于您的用例来说,它远不是一个完整的解决方案,但是您可以看看 unaccent.py this 第页。)

        11
  •  0
  •   Cœur Gustavo Armenta    6 年前

    杰夫·阿特伍德在他的博客上写了一篇好文章 Natural Sort Order pretty much what you ask