需求分析
option | description |
---|---|
-n, --numeric-sort | 按数值排序 |
-s,–split | 指定列分隔符,默认用空格 |
-k | 指定列号,支持多列 |
-r | 默认升序,-r让结果降序输出 |
-u | 去除重复项 |
-o | 指定输出文件 |
-h | 输出help信息 |
思路
读取文件并根据输入的命令将数据保存到二维数组中。比如 sortfile test -k 1,2,3;首先将test中的每一行用空格进行分割,然后将每行1-3列的内容添加到数组中,再把所分割行添加到数组中,这样得到了有四列数据的二维数组。我们要对前三列进行排序,排序之后输出第四列到指定文件就完成了对文件的排序。
核心问题
这个问题的关键就是对二维数组按列进行排序,可以采用常见的比较排序算法来比较(归并、冒泡等),但是要注意一个问题,因为存在对多列进行排序的可能,所以选择的排序算法必须是稳定的,诸如快排之类的不稳定排序是无法使用的。再有就是比较排序虽然比较的是每一行的列值,但是交换的时候是按一整行进行交换。
if($data->[$i][$colNum] < $data->[$j][$colNum]){
$data->[$i],$data->[$j] = $data->[$j],$data->[$i];
}
除了可以自己写排序算法,也可以使用 perl 中自带的强大的 sort 函数来进行排序。(文章推荐使用 perl 自带的 sort)。代码如下:
sub sort_by_col{
my $table_ref = shift;
my $sid = shift;
my $isNumber = shift;
if($isNumber){
@$table_ref = sort{$a->[$sid] <=> $b->[$sid]} @$table_ref;
}else{
@$table_ref = sort{$a->[$sid] cmp $b->[$sid]} @$table_ref;
}
}
稍微解释一下 sort 函数的用法,sort 通过变量 a 和 b 来访问 {} 后的列表中的元素,宇宙飞船符 “<=>” 代表了按数值比较,返回值为 -1,0,1;分别对应着小于,等于和大于,cmp代表了ASCII码比较,返回值也是 -1,0,1。sort 的返回值是排序后的数组。所以代码中比较的是二维数组的列值,交换的却是该数据所对应的行地址。实现了按列排序。
结果展示
原始数据
sortfile test -k 1 -n;
sortfile test -k 2 -n;
sortfile test -k 1,2 -n;
可以看到由于 perl 自带的 sort 函数是稳定的所以执行第一行命令的时候并没有改变文件的顺序。由于第一列的值完全相同,所以第二、三条命令的结果保持一致。
总结
perl 中的 sort 具有强大的功能,本文只是介绍了其中的一种简单应用,实现二维数组的按列排序,其实利用 sort 还能实现许多别的功能。