这篇文章的写成主要参考了ace_fei的内容,其中我认为有错误的地方,并进行了修改。网页如下:http://blog.csdn.net/ace_fei/article/details/7679609,大家可以到哪里去比较参考。
加入我们有这样一个文件,他的内容如下:
4 6 3
4 5 1
1 2 3
1 9 0
2 0 5
3 6 2
2 0 8
2 0 6
当然可能更多,我们排序的规则如下:
首先按照第一列排序,如果第一列相等,那么就按照第二列进行排序,如果第二列相等就按照第三列的内容排序。
我们先把问题最简单化,把上述的数字放到一个数组中;然后进行排序;
程序如下:
use strict;
use warnings;
my @num;
my @out;
my $out;
my $num;
@num=(
[qw[4 6 3]],
[qw[4 5 1]],
[qw[1 2 3]],
[qw[1 9 0]],
[qw[2 0 5]],
[qw[3 6 2]],
[qw[2 0 8]],
[qw[2 0 6]],
);
@out = sort {$a->[0] <=> $b->[0]
or $a->[1] <=> $b->[1]
or $a->[2] <=> $b->[2]} @num;
for $out (@out)
{
print "@$out\n";
}
得到的结果如下:
C:\WINDOWS\system32\cmd.exe /c perl "F:\perl\b.pl"
1 2 3
1 9 0
2 0 5
2 0 6
2 0 8
3 6 2
4 5 1
4 6 3
Hit any key to close this window...
当然你也可以按照第一列升序,如果第一列相同,第二列降序,如果第二列相同,第三列升序。
use warnings;
my @num;
my @out;
my $out;
my $num;
@num=(
[qw[4 6 3]],
[qw[4 5 1]],
[qw[1 2 3]],
[qw[1 9 0]],
[qw[2 0 5]],
[qw[3 6 2]],
[qw[2 0 8]],
[qw[2 0 6]],
);
@out = sort {$a->[0] <=> $b->[0]
or $b->[1] <=> $a->[1]
or $a->[2] <=> $b->[2]} @num;
for $out (@out)
{
print "@$out\n";
}
结果如下:
C:\WINDOWS\system32\cmd.exe /c perl "F:\perl\b.pl"
1 9 0
1 2 3
2 0 5
2 0 6
2 0 8
3 6 2
4 6 3
4 5 1
Hit any key to close this window...
当然我们要处理的东西,一般都不会直接放在数组中,而是一个放在一个文件中,我们就要先对文件进行处理;
现在我们把
4 6 3
4 5 1
1 2 3
1 9 0
2 0 5
3 6 2
2 0 8
2 0 6
放入一个dna.txt的文件夹中
程序如下:
use strict;
use warnings;
my @out;
my $out;
open(IN,"f:\\perl\\dna.txt") || die("can not open");
@out = sort {$a->[0] <=> $b->[0]
or $b->[1] <=> $a->[1]
or $a->[2] <=> $b->[2]}
map [(split)],<IN>;
for $out(@out)
{
print "@$out\n";
}
这里和ace fei有很大的不同,我不知道他们最后的结果是怎么得出来的。
因为我用那个程序得出的结果一直是不正确的
我们先来看一下正确的结果:
C:\WINDOWS\system32\cmd.exe /c perl "F:\perl\b.pl"
1 9 0
1 2 3
2 0 5
2 0 6
2 0 8
3 6 2
4 6 3
4 5 1
Hit any key to close this window...
我们再来分析一下ace fei的程序;
use strict;
use warnings;
my @out;
my $out;
open(IN,"f:\\perl\\dna.txt") || die("can not open");
@out = sort {$a->[0] <=> $b->[0]
or $b->[1] <=> $a->[1]
or $a->[2] <=> $b->[2]}
map [$_,(split)],<IN>;
for $out(@out)
{
print "@$out\n";
}
两者的不同点在于map后面的内容,我修改以后中括号内只留下了(split),因为如果有$_也留下的话,程序会报错,并且都是双行显示。
如下:
C:\WINDOWS\system32\cmd.exe /c perl "F:\perl\b.pl"
Argument "4 5 1\n" isn't numeric in numeric comparison (<=>) at F:\perl\b.pl li
e 9, <IN> line 8.
Argument "4 6 3\n" isn't numeric in numeric comparison (<=>) at F:\perl\b.pl li
e 9, <IN> line 8.
Argument "1 9 0\n" isn't numeric in numeric comparison (<=>) at F:\perl\b.pl li
e 9, <IN> line 8.
Argument "1 2 3\n" isn't numeric in numeric comparison (<=>) at F:\perl\b.pl li
e 9, <IN> line 8.
Argument "3 6 2\n" isn't numeric in numeric comparison (<=>) at F:\perl\b.pl li
e 9, <IN> line 8.
Argument "2 0 5\n" isn't numeric in numeric comparison (<=>) at F:\perl\b.pl li
e 9, <IN> line 8.
Argument "2 0 6\n" isn't numeric in numeric comparison (<=>) at F:\perl\b.pl li
e 9, <IN> line 8.
Argument "2 0 8\n" isn't numeric in numeric comparison (<=>) at F:\perl\b.pl li
e 9, <IN> line 8.
1 2 3
1 2 3
1 9 0
1 9 0
2 0 5
2 0 5
2 0 8
2 0 8
2 0 6
2 0 6
3 6 2
3 6 2
4 5 1
4 5 1
4 6 3
4 6 3
Hit any key to close this window...
其实我们从最根本的结构上来分析,很容易得出结论:
这里只不过是sort的一个更复杂的用法,
sort后面紧跟着的是你选择的排序方法,然后后面是数组,我们最后一个map的目的就是得出一个让sort可以用的数组
[split],<in>其实就是[split/\s/,$_],<in>的缩写,我实在想不明白,他把$_放在前面是干什么的?并且加在前面也会导致重复输出。
我们按照[split/\s/,$_],<in>的写法看看,
程序如下:
use strict;
use warnings;
my @out;
my $out;
open(IN,"f:\\perl\\dna.txt") || die("can not open");
@out = sort {$a->[0] <=> $b->[0]
or $b->[1] <=> $a->[1]
or $a->[2] <=> $b->[2]}
map [(split/\s/,$_)],<IN>;
for $out(@out)
{
print "@$out\n";
}
结果如下:
C:\WINDOWS\system32\cmd.exe /c perl "F:\perl\b.pl"
1 9 0
1 2 3
2 0 5
2 0 6
2 0 8
3 6 2
4 6 3
4 5 1
Hit any key to close this window...