我正在尝试使用Perl对具有特定字母顺序的名称列表进行排序,以执行一些特殊功能.
排序的工作方式sort { $a cmp $b }
与使用不同连续字母的方式相同.
例如,使用任意字符顺序"abdrtwsuiopqe987654"进行排序......
我试图处理,sort { $a myFunction $b }
但我是Perl的新手,我不知道如何正确组织myFunction
以获得我想要的东西.
cmp
使用Perl实现的功能,看它是如何工作的?以下可能是最快的[1]:
sub my_compare($$) {
$_[0] =~ tr{abdrtwsuiopqe987654}{abcdefghijklmnopqrs}r
cmp
$_[1] =~ tr{abdrtwsuiopqe987654}{abcdefghijklmnopqrs}r
}
my @sorted = sort my_compare @unsorted;
Run Code Online (Sandbox Code Playgroud)
或者如果你想要更动态的东西,以下可能是最快的[2]:
my @syms = split //, 'abdrtwsuiopqe987654';
my @map; $map[ord($syms[$_])] = $_ for 0..$#syms;
sub my_compare($$) {
(pack 'C*', map $map[ord($_)], unpack 'C*', $_[0])
cmp
(pack 'C*', map $map[ord($_)], unpack 'C*', $_[1])
}
my @sorted = sort my_compare @unsorted;
Run Code Online (Sandbox Code Playgroud)
我们可以通过比较字符字符,但会远远慢.
use List::Util qw( min );
my @syms = split //, 'abdrtwsuiopqe987654';
my @map; $map[ord($syms[$_])] = $_ for 0..$#syms;
sub my_compare($$) {
my $l0 = length($_[0]);
my $l1 = length($_[1]);
for (0..min($l0, $l1)) {
my $ch0 = $map[ord(substr($_[0], $_, 1))];
my $ch1 = $map[ord(substr($_[1], $_, 1))];
return -1 if $ch0 < $ch1;
return +1 if $ch0 > $ch1;
}
return -1 if $l0 < $l1;
return +1 if $l0 > $l1;
return 0;
}
my @sorted = sort my_compare @unsorted;
Run Code Online (Sandbox Code Playgroud)
从技术上讲,使用GRT可以更快地完成.
my @sorted =
map /\0(.*)/s,
sort
map { tr{abdrtwsuiopqe987654}{abcdefghijklmnopqrs}r . "\0" . $_ }
@unsorted;
Run Code Online (Sandbox Code Playgroud)从技术上讲,使用GRT可以更快地完成.
my @sorted =
map /\0(.*)/s,
sort
map { ( pack 'C*', map $map[ord($_)], unpack 'C*', $_ ) . "\0" . $_ }
@unsorted;
Run Code Online (Sandbox Code Playgroud)cmp
由scmp
运营商实施.
$ perl -MO=Concise,-exec -e'$x cmp $y'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <#> gvsv[*x] s
4 <#> gvsv[*y] s
5 <2> scmp[t3] vK/2
6 <@> leave[1 ref] vKP/REFC
Run Code Online (Sandbox Code Playgroud)
该scmp
操作是由实现pp_scmp
在功能上pp.c
,它实际上只是一个包装器sv_cmp_flags
中sv.c
时,use locale;
实际上是没有的.sv_cmp_flags
要么使用C库函数,要么使用memcmp
UTF-8感知版本(取决于标量的类型).