您可以使用Schwartzian 变换:
my @sorted = map { $_->[1] }
sort { $a->[0] <=> $b->[0] }
map { [ $lookup{$_->{bug_severity}, $_ ] }
@unsorted;
解释:
map { [ $lookup{$_->{bug_severity}, $_ ] } @unsorted;
将每个错误映射到一个数组引用,其第一个元素是查找表中的数字错误严重性。使用 Schwartzian 变换,您只需为@unsorted
.
然后,
sort { $a->[0] <=> $b->[0] }
按第一个元素对该数组进行排序。最后,
@sorted = map { $_->[1] }
从 . 返回的数组中提取原始错误sort
。
getval
当它所做的只是哈希查找时,真的没有必要。
对于自动生成高效的排序器,CPAN 模块Sort::Maker非常棒:
use strict; use warnings;
use Sort::Maker;
my @bugs = (
{ name => 'bar', bug_severity => 'severe' },
{ name => 'baz', bug_severity => 'noncritical' },
{ name => 'foo', bug_severity => 'critical' },
);
my $sorter = make_sorter('ST',
name => 'severity_sorter',
init_code => 'my %lookup = (
critical => 0,
severe => 1,
noncritical => -1 );',
number => [ code => '$lookup{$_->{bug_severity}}' ],
);
use Data::Dumper;
print Dumper $_ for severity_sorter( @bugs );
输出:
$VAR1 = {
'名称' => 'baz',
'bug_severity' => '非关键'
};
$VAR1 = {
'名称' => 'foo',
'bug_severity' => '关键'
};
$VAR1 = {
'名称' => '酒吧',
'bug_severity' => '严重'
};
请注意,使用 naive 方法时需要进行的查找次数取决于@unsorted
. 我们可以使用简单的程序计算它们:
#!/usr/bin/perl
use strict;
use warnings;
my ($n_elements) = @ARGV;
my @keys = qw(a b c);
my %lookup = map { $keys[$_-1] => $_ } 1 .. @keys;
my @unsorted = map { $keys[rand 3] } 1 .. $n_elements;
my $n_lookups;
my @sorted = sort {
$n_lookups += 2;
$lookup{$a} <=> $lookup{$b}
} @unsorted;
print "It took $n_lookups lookups to sort $n_elements elements\n";
输出:
C:\Temp> tzt 10
对 10 个元素进行排序需要 38 次查找
C:\Temp> tzt 100
对 100 个元素进行排序需要 978 次查找
C:\Temp> tzt 1000
对 1000 个元素进行排序需要 10916 次查找
C:\Temp> tzt 10000
对 10000 个元素进行排序需要 113000 次查找
因此,需要更多信息来确定朴素排序还是使用施瓦茨变换是合适的解决方案。
这是一个简单的基准,似乎与@Ether 的论点一致:
#!/usr/bin/perl
use strict;
use warnings;
use Benchmark qw( cmpthese );
my ($n_elements) = @ARGV;
my @keys = qw(foo bar baz);
my %lookup = map { $keys[$_] => $_ } 0 .. $#keys;
my @unsorted = map { {v => $keys[rand 3]} } 1 .. $n_elements;
cmpthese(-1, {
naive => sub {
my @sorted = sort {
$lookup{$a->{v}} <=> $lookup{$b->{v}}
} @unsorted;
},
schwartzian => sub {
my @sorted = map { $_->[1] }
sort { $a->[0] <=> $b->[0] }
map { [$lookup{$_->{v}}, $_] }
@unsorted;
}
});
输出:
C:\Temp> tzt 10
评价施瓦茨式的天真
施瓦茨 18842/s -- -29%
天真 26357/s 40% --
C:\Temp> tzt 100
评价天真的施瓦茨安
天真 1365/s -- -11%
施瓦茨 1532/s 12% --
C:\Temp> tzt 1000
评价天真的施瓦茨安
幼稚 121/s -- -11%
schwartzian 135/s 12% --