【问题标题】:Using "sort" for utf8 strings in Perl在 Perl 中对 utf8 字符串使用“排序”
【发布时间】:2018-03-18 22:21:24
【问题描述】:

我试图弄清楚如何在 Perl 中按字母顺序对数组进行排序。这是我在英语中可以正常工作的内容:

   # List of countries (kept like this to keep clean, as its re-used in other places)
    my $countries = {
        'AT' => "íAustria",
        'AU' => "Australia",
        'BE' => "Belgium",
        'BG' => "Bulgaria",
        'CA' => "Canada",
        'CY' => "Cyprus",
        'CZ' => "Czech Republic",
        'DK' => "Denmark",
        'EN' => "England",
        'EE' => "Estonia",
        'FI' => "Finland",
        'FR' => "France",
        'DE' => "Germany",
        'GB' => "Great Britain",
        'GR' => "Greece",
        'HU' => "Hungary",
        'IE' => "Ireland",
        'IT' => "Italy",
        'LV' => "Latvia",
        'LT' => "Lithuania",
        'LU' => "Luxembourg",
        'MT' => "Malta",
        'NZ' => "New Zealand",
        'NL' => "Netherlands",
        'PL' => "Poland",
        'PT' => "Portugal",
        'RO' => "Romania",
        'SK' => "Slovakia",
        'SI' => "Slovenia",
        'ES' => "Spain",
        'SE' => "Sweden",
        'CH' => "Switzerland",
        'SC' => "Scotland",
        'UK' => "United Kingdom",
        'US' => "USA",
        'TK' => "Turkey",
        'NO' => "Norway",
        'MX' => "Mexico",
        'IL' => "Israel",
        'IN' => "India",
        'IS' => "Iceland",
        'CN' => "China",
        'JP' => "Japan",
        'VN' => "áVietnamí"
    };
   # Populate the original loop with "name" and "code"
    my @country_loop_orig;
    print $IN->header;
    foreach (keys %{$countries}) {
      push @country_loop_orig, {
        name => $countries->{$lang}->{$_},
        code => $_
      }
    }

   # sort it alphabetically
   my @country_loop = sort { lc($a->{name}) cmp lc($b->{name})  } @country_loop_orig;

这适用于英文版本:

Australia
Austria
Belgium
Bulgaria
Canada
China
Cyprus
Czech Republic
Denmark
England
Estonia
Finland
France
Germany
Great Britain
Greece
Hungary
Iceland
India
Ireland
Israel
Italy
Japan
Latvia
Lithuania
Luxembourg
Malta
Mexico
Netherlands
New Zealand
Norway
Poland
Portugal
Romania
Scotland
Slovakia
Slovenia
Spain
Sweden
Switzerland
Turkey
United Kingdom
USA
Vietnam

...但是当您尝试使用 íéó 等 utf8 执行此操作时,它不起作用:

Australia
Belgium
Bulgaria
Canada
China
Cyprus
Czech Republic
Denmark
England
Estonia
Finland
France
Germany
Great Britain
Greece
Hungary
Iceland
India
Ireland
Israel
Italy
Japan
Latvia
Lithuania
Luxembourg
Malta
Mexico
Netherlands
New Zealand
Norway
Poland
Portugal
Romania
Scotland
Slovakia
Slovenia
Spain
Sweden
Switzerland
Turkey
United Kingdom
USA
áVietnam
íAustria

您是如何做到这一点的?我找到了Sort::Naturally::XS,但无法正常工作。

【问题讨论】:

  • cmp 对字符集和编码一无所知。它直接逐个字符(字符串元素)进行比较。 (除了可能在use locale; 下,您不应该使用它。)

标签: perl utf-8


【解决方案1】:

Unicode::Collate 应该对此有所帮助。

对最后一个列表进行排序的简单示例

use warnings;
use strict;
use feature 'say';

use Unicode::Collate;

use open ":std", ":encoding(UTF-8)";

open my $fh, '<', "country_list.txt";
my @list = <$fh>;
chomp @list;

my $uc  = Unicode::Collate->new();
my @sorted = $uc->sort(@list);

say for @sorted;

但是,在某些语言中,非 ascii 字符可能具有非常特殊的可接受位置,并且该问题未提供 任何 详细信息。那么也许Unicode::Collate::Locale 可以提供帮助。

请参阅(研究)this perl.com articlethis post (T. Christiansen) 和 this Effective Perler article


如果要排序的数据是复杂的数据结构,cmp方法是单独比较

my @sorted = map { $uc->cmp($a, $b) } @list;

对于$a$b,您将从复杂的数据结构中提取需要比较的内容。

【讨论】:

  • 太棒了,谢谢。您将如何对数组中的哈希进行排序?例如我在做$a-&gt;{name} cmp $b-&gt;{name}?
  • 顺便说一句,当我只对一个名称数组进行排序时(没有将其作为哈希结构),它可以完美地工作。我想我可以重新设计我的数据存储方式,但我会等着看是否有更好的方法,然后再花很多时间这样做:)
  • @AndrewNewby 使用cmp 方法,@s = sort { $uc-&gt;cmp($a, $b) } @list;,进行个别比较
  • 你的传奇!像魅力一样工作:my $uc = Unicode::Collate-&gt;new(); my @country_loop = sort { $uc-&gt;cmp($a-&gt;{name}, $b-&gt;{name}) } @country_loop_orig;
  • @AndrewNewby Cool :) 刚刚为它添加了注释
猜你喜欢
  • 1970-01-01
  • 2016-05-31
  • 2015-07-11
  • 2021-03-17
  • 1970-01-01
  • 1970-01-01
  • 2015-12-13
  • 1970-01-01
  • 2013-05-04
相关资源
最近更新 更多