Perl:先按值排序散列,然后按键排序

Perl:先按值排序散列,然后按键排序,perl,Perl,与这个问题类似: 我想先按值排序,然后按键的子集排序 我的%hash: cat_02 => 0 cat_04 => 1 cat_03 => 0 cat_01 => 3 输出(可以是按此顺序排列的键数组): 额外好处:关键的二次比较将识别1234_2_C01并小于1234_34_C01(不)。使用: my %hash = ( cat_02 => 0, cat_04 => 1, cat_03 => 0, cat_01 => 3

与这个问题类似:

我想先按值排序,然后按键的子集排序

我的
%hash

 cat_02 => 0
 cat_04 => 1
 cat_03 => 0
 cat_01 => 3
输出(可以是按此顺序排列的键数组):

额外好处:关键的二次比较将识别1234_2_C01并小于1234_34_C01(不)。使用:

my %hash = (
  cat_02 => 0,
  cat_04 => 1,
  cat_03 => 0,
  cat_01 => 3
);

print "$_ => $hash{$_}\n"
  for sort { $hash{$a} <=> $hash{$b} or $a cmp $b } keys %hash;
my%hash=(
类别02=>0,
类别04=>1,
cat_03=>0,
cat_01=>3
);
打印“$\=>$hash{$\}\n”
对于排序{$hash{$a}$hash{$b}或$a cmp$b}键%hash;
排序对值进行数字比较,如果它们相等,则执行
之后的部分,对键进行字符串比较。这将提供您要求的输出


对于包含数字与非数字内容混合的字符串的智能排序,请从中获取alphanum比较函数,并将
$a cmp$b
替换为
alphanum($a,$b)

当您具有第二排序首选项时,只需在排序例程中添加另一个级别:

my %hash = (
    cat_02 => 0,
    cat_04 => 1,
    cat_03 => 0,
    cat_01 => 3
);

my @sorted = sort { $hash{$a} <=> $hash{$b} || $a cmp $b } keys %hash;
                  #  primary sort method    ^^ secondary sort method
for (@sorted) {
    print "$_\t=> $hash{$_}\n";
}

在这种特殊情况下可能不值得这样做,但这种技术也可以用于多标准排序。像这样():

使用Sort::Key::modules可以轻松(快速)完成此操作:

use Sort::Key::Natural qw( );
use Sort::Key::Maker intnatkeysort => qw( integer natural );

my @sorted_keys = intnatkeysort { $hash{$_}, $_ } keys(%hash);
或者,您可以利用数据的属性,只需使用自然排序:

use Sort::Key::Natural qw( natkeysort );

my @sorted_keys = natkeysort { "$hash{$_}-$_" } keys(%hash);

cmp对字符串中的数字和字母有什么影响,比如说,你用1234\u 2\u C01\u HT1和1234\u 23\u C01\u HT2键代替cat。@Jabda,
cmp
按字典顺序进行比较,即
12 cmp 2
将生成
-1
,而
12 2
将生成
1
。作为一种特殊情况,如果两个数字中的数字数量相同,
cmp
将产生相同的结果。
2
在数字和字符串上都小于
34
,因此这是一个坏例子。但我知道你的意思。更新了我的回答没有“级别”、“主要排序方法”或“次要排序方法”,只是布尔表达式首先比较值,如果值相等,则比较键。我的意思是,目前的解释看起来像是“这是一种神奇的语法,可以按
x
然后按
y
排序”。当然有排序方法,从优先级的角度来看,其中一种是主要的,另一种是次要的。它不是神奇的,不,正如代码中显而易见的那样,它只是使用逻辑OR运算符。
use warnings;
use strict;

my %myhash = (
  cat_2 => 0, cat_04 => 1,
  cat_03 => 0, dog_02 => 3, 
  cat_10 => 0, cat_01 => 3,
);

my @sorted = 
    map { [$_->[0], $myhash{$_->[0]}] } 
    sort { $a->[1] <=> $b->[1]  or  $a->[2] <=> $b->[2] } 
    map { m/([0-9]+)$/ && [$_, $myhash{$_}, $1] } 
    keys %myhash;

print $_->[0] . ' => ' . $_->[1] . "\n" for @sorted;
    map { m/_([0-9]+)_/ && [$_, $myhash{$_}, $1] } 
use Sort::Key::Natural qw( );
use Sort::Key::Maker intnatkeysort => qw( integer natural );

my @sorted_keys = intnatkeysort { $hash{$_}, $_ } keys(%hash);
use Sort::Key::Natural qw( natkeysort );

my @sorted_keys = natkeysort { "$hash{$_}-$_" } keys(%hash);