在哈希的小写键值之前排序大写

时间:2011-02-10 09:03:42

标签: perl sorting hash

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

示例:



JIM
吉姆

4 个答案:

答案 0 :(得分:12)

要按顺序获取密钥,请在哈希的密钥上应用带有自定义排序功能的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首先比较字符串,就好像它们是相同的情况一样,如果相等则考虑大小写。

答案 1 :(得分:8)

使用自定义排序,首先根据其较低的表示形式比较项目(以便“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

答案 2 :(得分:8)

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

Fancier Alphabetic Sorts of 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";

制作'correcter'(读:无限优先)版本:

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 l m n n o p q r rr s t u v x w z z
  • 西班牙语(最近):a b c d e f g h i j k l m n n o p q r s t u v x w y z
  • 加泰罗尼亚语:a bcçde 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 ff g ng h l l n n p p r r s s 丹麦语:a b c d e f g h i j k l m n o p q r s t u v w x yzæøå
  • 冰岛语:aábdðeéfg hiíjk l m noópr s tuúvx yýææö
  • 古英语:a b c d e fȝ/ g h i k l m n o p q r s t v x y z&amp; ⁊ƿþðæ
  • 中古英语:a b c d e f g h i k l m n o p q s s / s t v x y zȝƿþææ
  • Futhorc(译音)表示:f第u个öR Cȝ瓦特H N I J EO P X [式T Bé米L N dœ一个æÿEA IO CWķST克
  • 希腊语:αβγδεζηθικλμνξοπρσ/ςτυφχψω
  • 西里尔:абвгдеёжзийклмнопрстуфхцчшщъыьэюя
  • 切诺基:ᎠᎡᎢᎣᎤᎥᎦᎧᎨᎩᎪᎫᎬᎭᎮᎯᎰᎱᎲᎳᎴᎵᎶᎷᎸᎹᎺᎻᎼᎽᎾᎿᏀᏁᏂᏃᏄᏅᏆᏇᏈᏉᏊᏋᏌ ᏍᏎᏏᏐᏑᏒᏓᏔᏕᏖᏗᏘᏙᏚᏛᏜᏝᏞᏟᏠᏡᏢᏣᏤᏥᏦᏧᏨᏩᏪᏫᏬᏭᏮᏯᏰᏱᏲᏳᏴ
顺便说一下,这些也是很好的例子,为什么“将[a-z]硬编码到你的程序中总是错误的,有时。”它充满了愚蠢甚至侮辱假设。 请注意,除了最后三个之外的所有内容实际上都被认为是拉丁字母!这与我们在英语中使用的脚本相同。在代表的英语文字,我已经不同了,处理的据悉,伊尼伊德,PO英尺,Laȝamon,简历,1ˢᵗ,MᶜKinley,凡Dijke,佳能市科罗拉多,酿酒,Dzur,角色, ⅷ,première,Bjørn,naïve,coöperate,façade,café,Merððyn,archæology,甚至tschüß。重复口头禅:“将[a-z]硬编码到你的程序中总是错误的,有时。”只是说不!

Unicode :: Collat​​e :: Locale模块处理本地排序约定。就像英语电话簿和书架有特殊的方式对名称进行排序一样,无论你是拼写了什么 McBride 还是 MacBride ,德语世界都会对它们进行排序。这些名称​​Händel Haendel 是相同的。这就是为什么没有变音符号,一个必须强制性写的尤伯杯 - 的作为的 ueber - 超人的作为的 Uebermensch < / em>的。区域设置排序知道这样做:

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”语言环境略有不同;从历史上看,巧克力在西班牙语词典中之后 color ,与它在Enlgish中的工作方式不同。那是因为 ch c 之后和 d 之前,而 ll l 之后在 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

答案 3 :(得分:6)

尝试:

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