【问题标题】:sort upper case just before lowercase key values from a hash在哈希中的小写键值之前对大写进行排序
【发布时间】:2011-06-24 17:09:06
【问题描述】:

我有一个哈希值,我想根据大写单词出现在小写单词之前的键进行排序。

例子:



吉姆
吉姆

【问题讨论】:

  • 您的意思是要按特定顺序提取密钥吗?您无法对键的实际存储进行排序,因为散列键是无序的。
  • 不,我只想按排序顺序打印出来。实际上并没有在哈希中按排序顺序保存键。

标签: perl sorting hash


【解决方案1】:

试试:

@list = ("jane","JIM","JANE","jim");
print sort { uc $a cmp uc $b or $a cmp $b } @list;

【讨论】:

    【解决方案2】:

    要按顺序获取键,请在散列的键上应用 sort 和自定义排序功能。

    my %hash = ( JANE => 1, jane => 2, JIM => 3, jim => 4 );
    my @sorted_keys = sort {
        lc $a cmp lc $b
            || $a cmp $b
    } keys %hash;
    

    custom sort function 首先比较字符串,就好像它们的大小写相同,如果相等,则考虑大小写。

    【讨论】:

    • 第一个小写可以将比较改为lc $a cmp lc $b || $b cmp $a
    【解决方案3】:

    使用自定义排序,首先根据项目的小写表示比较项目(以便“jane”的所有变体出现在“jim”的变体之前),然后通过执行默认的 ASCII 比较来解决平局问题(其中大写在小写之前):

    perl -e 'print join "\n", sort { lc $a cmp lc $b || $a cmp $b } qw( jim JANE jane JIM )'
    

    输出:

    JANE
    jane
    JIM
    jim
    

    【讨论】:

      【解决方案4】:

      Unicode 排序规则

      虽然这个操作看起来有点矫枉过正,但标准的 Unicode::Collat​​e 和 Unicode::Collat​​e::Locale 模块就是为这种事情而设计的。它们还按字母顺序对非 ASCII 数据进行排序,而普通的 sort 不会这样做。

      use utf8;
      @names = qw[ jim JANE jane JIM josé josie Mary María mark ];
      @sorts = sort @names;
      

      这为您提供了

      的排序顺序
      JANE JIM Mary María jane jim josie josé mark
      

      没有人想要。这好多了:

      use utf8;
      use Unicode::Collate;
      @names = qw[ jim JANE jane JIM josé josie Mary María mark ];
      $coll = new Unicode::Collate;
      @sorts = $coll->sort(@names);
      

      这给了你

      jane JANE jim JIM josé josie María mark Mary
      

      如果你想在小写之前使用大写,请这样指定:

      use utf8;
      use Unicode::Collate;
      @names = qw[ jim JANE jane JIM josé josie Mary María mark ];
      $coll = new Unicode::Collate upper_before_lower => 1;
      @sorts = $coll->sort(@names);
      print "@sorts\n";
      

      产生:

      JANE jane JIM jim josé josie María mark Mary
      

      简单比较

      您可以以习惯的方式在一对字符串上使用排序规则对象的 cmp 方法,例如

      #!/usr/bin/env perl
      
      use 5.10.1;
      use strict;
      use autodie; 
      use warnings qw[ FATAL all ];
      use utf8;
      use open qw[ :std IO :utf8 ];
      use Unicode::Collate;
      
      my @names = qw[ fum fee fie foe ];
      my $coll = Unicode::Collate->new;
      my @sorts = $coll->sort(@names);
      say "@names => @sorts\n";
      
      for (
            my($a, $b) = splice @names, 0, 2;
            2 == grep {defined} $a, $b;
            ($a, $b) = ($b, shift @names)
          )
      {
          given ($coll->cmp($a, $b)) {
              when (-1) { say "$a < $b" }
              when ( 0) { say "$a = $b" }
              when (+1) { say "$a > $b" }
              default   { die "NOT REACHED" }
          }
      }
      

      产生:

      fum fee fie foe => fee fie foe fum
      
      fum > fee
      fee < fie
      fie < foe
      

      更高级的 Unicode 字母排序

      现在考虑这样的单词列表:

      sát sot sät sét sæt ssét sat tot ßet SET set seat ſAT ſet saet SSET
      

      如果你在上面运行默认排序,你会得到几乎无用的:

      SET SSET saet sat seat set sot ssét sát sät sæt sét tot ßet ſAT ſet
      

      而且区分大小写的排序真的再好不过了:

      use utf8;
      @names = qw[ sát sot sät sét sæt ssét sat tot ßet SET set seat ſAT ſet saet SSET ];
      @sorts = sort {
          lc $a  cmp  lc $b
                 ||
             $a  cmp  $b
      } @names;
      print "@sorts\n";
      

      产生仍然愚蠢和错误的:

      saet sat seat SET set sot SSET ssét sát sät sæt sét tot ßet ſAT ſet
      

      但这里是标准的 Unicode 排序:

      use utf8;
      use Unicode::Collate;
      @names = qw[ sát sot sät sét sæt ssét sat tot ßet SET set seat ſAT ſet saet SSET ];
      $coll = new Unicode::Collate upper_before_lower => 1;
      @sorts = $coll->sort(@names);
      print "@sorts\n";
      

      产生“更正”(阅读:无限优选)版本:

      saet sæt sät sat sát ſAT seat SET set sét ſet sot SSET ssét ßet tot
      

      语言环境排序

      Unicode::Collat​​e 模块非常快,因此您应该毫不犹豫地在您的路线字符排序需求中使用它。但有时这还不够。那是因为不同的语言有不同的字母概念。

      • 拉丁文(古):a b c d e f z h i k l m n o p q r s t v x
      • 拉丁文(经典):a b c d e f g h i k l m n o p q r s t v x y z
      • 西班牙语(传统):a b c ch d e f g h i j k l ll m n ñ o p q r rr s t u v x w y z
      • 西班牙语(近期):a b c d e f g h i j k l m n ñ o p q r s t u v x w y z
      • 加泰罗尼亚语:a b c ç d e f g h i j k l m n o p q r s t u v x w y z
      • 威尔士语:a b c ch d dd e f ff g ng h i l ll m n o p ph r rh s t th u w y
      • 丹麦语:a b c d e f g h i j k l m n o p q r s t u v w x y z æ ø å
      • 冰岛语:a á b d ð e é f g h i í j k l m n o ó p r s t u ú v x y ý þ æ ö
      • 古英语:a b c d e f ȝ/g h i k l m n o p q r s t v x y z & ⁊ ƿ þ ð æ
      • 中古英语:a b c d e f g h i k l m n o p q r ſ/s t v x y z ȝ ƿ þ ð æ
      • Futhorc(音译):f u þ o r c ȝ w h n i j eo p x s t b e m l ŋ d – a æ y ea io cw k st g
      • 希腊语:α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ σ/ς τ υ φ χ ψ ω
      • 西里尔字母:а б в г д е ё ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э ю я
      • Cherokee:ꭰꭰꭱꭲꭳꭴꭵꭶꭷꭸꭹꭺꭻꭼꭾꭿꮀꮁꮂꮂꮃꮄꮆꮇꮈꮉꮊꮊꮋꮋꮎꮐꮐꮑꮒꮒꮓꮓꮐꮏꮐꮑꮒꮛꮘ 

      顺便说一句,这些也是为什么“将[a-z] 硬编码到你的程序中总是错误的,有时”的很好的例子。它充满了愚蠢甚至侮辱性的假设。 请注意,除了最后三个之外,所有这些实际上都被视为拉丁字母!这与我们在英语中使用的脚本相同。在表示 English 文本时,我不得不处理各种不同的问题:learnèd、Æneid、poſt、Laȝamon、ressumé、1ˢᵗ、MᶜKinley、Van Dijke、Cañon City Colorado、œnology、Dzur、rôle、 ⅷ,首映,比约恩,天真,合作,立面,咖啡馆,Merððyn,考古学,甚至tschüß。重复口头禅:“将[a-z] 硬编码到您的程序中总是错误的,有时。”说不!

      Unicode::Collat​​e::Locale 模块处理本地排序约定。就像英语电话簿和书架有特殊的姓名排序方式一样,无论您拼写的是 McBride 还是 MacBride,德语世界也会对其进行排序。 HändelHaendel 的名称相同。这就是为什么没有变音符号,必须强制über- 写为 ueber- 并将 Übermensch 写为 Uebermensch。语言环境排序知道这样做:

      use utf8;
      use Unicode::Collate::Locale;
      @names = qw[ sát sot sät sét sæt ssét sat tot ßet SET set seat ſAT ſet saet SSET ];
      
      $coll = new Unicode::Collate::Locale::
                  locale             => de__phonebook,
                  upper_before_lower => 1,
              ;
      
      @sorts = $coll->sort(@names);
      print "@sorts\n";
      

      现在产生

      saet sæt sät sat sát ſAT seat SET set sét ſet sot SSET ssét ßet tot
      

      Se habla castellano

      令人惊讶的是,一个人的语言环境惯例与自己其他国家/地区的语言环境惯例有多么不同。在西班牙语言环境(“es”)中,ñ 是一个出现在 n 之后和 o 之前的字母。这意味着正确的类型

      raña rastrillo radio rana rápido ráfaga ranúnculo
      

      radio ráfaga rana raña ranúnculo rápido rastrillo
      

      用完全卷起的rr快速地说出所有这些来放松你的舌头。 :)

      “es__traditional”语言环境有点不同;从历史上看,chocolate 在西班牙语词典中 color 之后出现,这与它在英语中的使用方式不同。那是因为chc之后d之前,而lll之后在 m 之前。这意味着这个序列:

      lástima laña llama ligante
      cidra caliente color chocolate con churros
      pero pera Perú perro periglo peste
      

      排序

      caliente cidra color con chocolate churros 
      laña lástima ligante llama 
      pera periglo pero perro Perú peste
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-05-01
        • 2011-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-22
        • 2018-12-14
        • 2011-10-30
        相关资源
        最近更新 更多