Perl数字排序:如何忽略前导alpha字符

Luk*_*ard 2 arrays sorting perl

我有一个像这样的1,660行数组:

...
H00504
H00085
H00181
H00500
H00103
H00007
H00890
H08793
H94316
H00217
...
Run Code Online (Sandbox Code Playgroud)

而主角永远不会改变.它总是"H"然后是五位数.但是,当我在Perl中做我认为是数字排序时,我会得到奇怪的结果.某些段按顺序排序,但随后会启动另一个段.以下是排序后的细分:

...
H01578
H01579
H01580
H01581
H01582
H01583
H01584
H00536
H00537
H00538
H01585
H01586
H01587
H01588
H01589
H01590
...
Run Code Online (Sandbox Code Playgroud)

我正在尝试的是这个:

my @sorted_array = sort {$a <=> $b} @raw_array;
Run Code Online (Sandbox Code Playgroud)

但显然它不起作用.谁知道为什么?

我应该补充一点,虽然这些值都有"H"前置,但是将来我们可能会在其他字母前加上额外的数据.这意味着删除H,排序,然后替换H,不是解决方案

ike*_*ami 9

如果你use strict; use warnings;按照自己的意愿使用,那么你可能会遇到很多错误

Argument "H01578" isn't numeric in numeric comparison (<=>)
Run Code Online (Sandbox Code Playgroud)

你的元素都不是数字,所以它们都被认为是零.这就是Perl认为您当前代码的结果已排序的原因.


如果你想按字母排序,那么按数字排序(由于所有字母都相同,所以只按数字排序相同):

my @sorted_array = sort @raw_array;
Run Code Online (Sandbox Code Playgroud)

这是短的

my @sorted_array = sort { $a cmp $b } @raw_array;
Run Code Online (Sandbox Code Playgroud)

如果您想按编号排序而不考虑前导字母,则可以使用以下代码:

my @sorted_array =
   sort { substr($a, 1) <=> substr($b, 1) }
    @raw_array;
Run Code Online (Sandbox Code Playgroud)


Bor*_*din 5

如果要将初始字符排序为主键,然后将数字排序为辅助键,则可以使用Schwartzian变换的变体,该变换在排序之前从所有数据中提取两个字段以进行比较.

该计划表明

use strict;
use warnings;

my @data = <DATA>;
chomp @data;

my @sorted = sort map $_->[0],
sort { $a->[1] cmp $b->[1] or $a->[2] <=> $b->[2] }
map [$_, /(.)(.+)/], @data;

print "$_\n" for @sorted;

__DATA__
A1180
B0802
B1284
C0899
C1455
C0765
A1207
A0909
C0921
C1060
A1067
B1486
A1268
B0772
C0595
B0734
A1004
A0607
A1323
B1181
Run Code Online (Sandbox Code Playgroud)

产量

A0607
A0909
A1004
A1067
A1180
A1207
A1268
A1323
B0734
B0772
B0802
B1181
B1284
B1486
C0595
C0765
C0899
C0921
C1060
C1455
Run Code Online (Sandbox Code Playgroud)

工具成功完成

您可能更喜欢使用不使用Transform的替代方法.此程序具有相同的输出,但对于大型数据集,其运行速度要慢得多

my @sorted = sort {
  my @a = $a =~ /(.)(.+)/;
  my @b = $b =~ /(.)(.+)/;
  $a[0] cmp $b[0] or $a[1] <=> $b[1];
} @data;
Run Code Online (Sandbox Code Playgroud)