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

MBU*_*MBU 3 sorting perl hash

我有一个哈希,我想基于键,在小写单词之前出现大写单词.

例:

JANE

JIM
吉姆

Tim*_*Tim 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;
Run Code Online (Sandbox Code Playgroud)

自定义排序功能首先比较字符串,就好像它们是相同的情况一样,如果相等,则考虑大小写.


Dav*_*man 8

使用自定义排序,首先根据其较低的表示形式比较项目(以便"jane"的所有变体出现在"jim"的变体之前),然后通过执行默认的ASCII比较(其中大写字母在小写之前)来解析关系:

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

输出:

JANE
jane
JIM
jim
Run Code Online (Sandbox Code Playgroud)


tch*_*ist 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;
Run Code Online (Sandbox Code Playgroud)

这给你的排序顺序

JANE JIM Mary María jane jim josie josé mark
Run Code Online (Sandbox Code Playgroud)

没有人想要的.这要好得多:

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);
Run Code Online (Sandbox Code Playgroud)

那给了你

jane JANE jim JIM josé josie María mark Mary
Run Code Online (Sandbox Code Playgroud)

如果要在小写之前使用大写,请以这种方式指定:

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";
Run Code Online (Sandbox Code Playgroud)

产量:

JANE jane JIM jim josé josie María mark Mary
Run Code Online (Sandbox Code Playgroud)

简单比较

你可以cmp按照习惯的方式在一对字符串上使用collat​​ion对象的方法,比如

#!/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" }
    }
}
Run Code Online (Sandbox Code Playgroud)

产生:

fum fee fie foe => fee fie foe fum

fum > fee
fee < fie
fie < foe
Run Code Online (Sandbox Code Playgroud)

Fancier Alphabetic各种Unicode

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

sát sot sät sét sæt ssét sat tot ßet SET set seat ?AT ?et saet SSET
Run Code Online (Sandbox Code Playgroud)

如果你对它运行默认排序,你几乎无用:

SET SSET saet sat seat set sot ssét sát sät sæt sét tot ßet ?AT ?et
Run Code Online (Sandbox Code Playgroud)

区分大小写的排序实际上并不是更好:

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";
Run Code Online (Sandbox Code Playgroud)

产生仍然愚蠢的错误:

saet sat seat SET set sot SSET ssét sát sät sæt sét tot ßet ?AT ?et
Run Code Online (Sandbox Code Playgroud)

但这里是标准的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";
Run Code Online (Sandbox Code Playgroud)

产生'correcter'(读:无限优先)版本:

saet sæt sät sat sát ?AT seat SET set sét ?et sot SSET ssét ßet tot
Run Code Online (Sandbox Code Playgroud)

Locale Sorts

Unicode :: Collat​​e模块非常快,所以你不应该犹豫在你的路由字符排序需求上使用它.但有时候这还不够.那是因为不同的语言有不同的字母表思想.

  • 拉丁语(古代):abcdefzhiklmnopqrstvx
  • 拉丁语(经典):abcdefghiklmnopqrstvx yz
  • 西班牙语(繁体):abc ch defghijkl llmnñopqrrr stuvxwyz
  • 西班牙语(最近):abcdefghijklmn - opqrstuvxwyz
  • 加泰罗尼亚语:abcçdefghijklmnopqrstuvxwyz
  • 威尔士:abc ch d df ef ff g ng hl ll mnop ph r rh st uwy
  • 丹麦语:abcdefghijklmnopqrstuvwxyzæøå
  • 冰岛语:aábdðeéfghiíjklmnoóprstuúvxyýæöö
  • 古英语:abcdefȝ/ ghiklmnopqrstvxyz&⁊ƿþðæ
  • 中古英语:abcdefghiklmnopqr s/stvxyzȝƿþðæ
  • Futhorc(音译):fuþorcȝwhnij eo pxstbemlŋdœyea io cw k st g
  • 希腊语:αβγδεζηθικλμνξοπρσ/ςτυφχψω
  • 西里尔:абвгдеёжзийклмнопрстуфхцчшщъыьэюя
  • 切诺基:ᎠᎡᎢᎣᎤᎥᎦᎧᎨᎩᎪᎫᎬᎭᎮᎯᎰᎱᎲᎳᎴᎵᎶᎷᎸᎹᎺᎻᎼᎽᎾᎿᏀᏁᏂᏃᏄᏅᏆᏇᏈᏉᏊᏋᏌᏍᏎᏏ ᏐᏑᏒᏓᏔᏕᏖᏗᏘᏙᏚᏛᏜᏝᏞᏟᏠᏡᏢᏣᏤᏥᏦᏧᏨᏩᏪᏫᏬᏭᏮᏯᏰᏱᏲᏳᏴ

顺便说一句,这些也是很好的例子,为什么" 有时硬编码[a-z]到你的程序总是错误的."它充满了愚蠢甚至是侮辱性的假设. 请注意,除了最后三个之外的所有内容实际上都被认为是拉丁字母!这与我们在英语中使用的脚本相同.在代表英文文本,我已经不同了应对了解到,伊尼伊德,PO英尺,Laȝamon,简历,1ˢᵗ,MᶜKinley,凡Dijke,佳能市科罗拉多,酿酒,Dzur,角色,ⅷ,首映,比约恩,天真,合作, façade,café,Merððyn,archæology,甚至tschüß.重复口头禅:"硬编码[a-z]到你的程序总是错的,有时候."说不!

Unicode :: Collat​​e :: Locale模块处理本地排序约定.正如英语电话簿和书架有排序的名字特殊的方式,使不梅特您是否已经拼什么麦克布赖德麦克布赖德,在德语世界排序他们的名字,使得韩德尔亨德尔是相同的.这就是为什么没有变音符号,必须强制性地über-ueber-超人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";
Run Code Online (Sandbox Code Playgroud)

现在生产

saet sæt sät sat sát ?AT seat SET set sét ?et sot SSET ssét ßet tot
Run Code Online (Sandbox Code Playgroud)

Se habla castellano

与其他国家/地区的区域惯例有何不同,这是非常了不起的.在西班牙语语言环境("ES"),ñ是点之后,是信ñ之前Ò.这意味着正确的那种

raña rastrillo radio rana rápido ráfaga ranúnculo
Run Code Online (Sandbox Code Playgroud)

radio ráfaga rana raña ranúnculo rápido rastrillo
Run Code Online (Sandbox Code Playgroud)

用完全滚动的rr来说这些都非常快,以松开你的舌头.:)

"es__traditional"语言环境略有不同; 从历史上看,巧克力 西班牙语词典中以颜色出现的,与它在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
Run Code Online (Sandbox Code Playgroud)

排序到

caliente cidra color con chocolate churros 
laña lástima ligante llama 
pera periglo pero perro Perú peste
Run Code Online (Sandbox Code Playgroud)


dog*_*ane 6

尝试:

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