perl方法:sort函数 (转载)

本文介绍Perl中的排序技巧,包括Schwartzian转换和Guttman-Rosler转换等高级方法,适用于文件名按修改时间排序及表格数据按指定列排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

perl方法:sort函数
www.diybl.com 时间:2008-02-24 作者:佚名 编辑:本站 点击:  [评论]
-
-
] <=>; $b->;[1] }
              map({ [$_, -M] } @filenames)
            )
        );

这个code结合用了map,sort分了好几层,记住偶以前提过的方法,从后往前看。map({ [$_, -M] } @filenames)返回一个列表,列表元素是匿名数组,匿名数组的第一个值是文件名,第二个值是文件的修改日期。

sort( { $a->;[1] <=>; $b->;[1] }...再对上述产生的匿名数组列表进行sort,它根据文件的修改日期进行sort。sort返回的结果是经过排序后的匿名数组。

最外围的map( { $_->;[0] }...就简单了,它从上述sort产生的匿名数组里提取出文件名。这个文件名就是根据修改日期进行sort过的呀,并且每个文件只运行了一次-M。

这就是著名的Schwartzian转换,这种用法在国外perl用户里很流行。记住仙子告诉你的Schwartzian概念哦,下次就不会被老外laugh at了,:p

本文作者说:

Orcish算法通常更难于编码,并且不如Schwartzian转换文雅。我推荐你使用Schwartzian转换作为可选择的方法。

也请记住基本的优化code的规则:(1)不写code;(2)在使code快速之前,先保证其正确;(3)在使code快速之前,先让它清楚。

10. 根据最后一列来对行进行sort(Schwartzian转换)

假如$str的值如下(每行以/n终结):

eir   11   9   2   6   3   1   1   81%   63%   13
oos   10   6   4   3   3   0   4   60%   70%   25
hrh   10   6   4   5   1   2   2   60%   70%   15
spp   10   6   4   3   3   1   3   60%   60%   14

按最后1个域的大小进行sort:

$str = join "/n",
        map { $_->;[0] }
          sort { $a->;[1] <=>; $b->;[1] }
              map { [ $_, (split)[-1] ] }
                split //n/, $str;

打印结果是:

eir   11   9   2   6   3   1   1   81%   63%   13
spp   10   6   4   3   3   1   3   60%   60%   14
hrh   10   6   4   5   1   2   2   60%   70%   15
oos   10   6   4   3   3   0   4   60%   70%   25

让我们从后往前,一步一步看上述code:

split //n/, $str; 这里返回一个列表,列表元素就是各个行了。

map { [ $_, (split)[-1] ] } 这里的map求得一个匿名数组列表,匿名数组的值分别是整行,和该行的最后一列。使用Schwartzian转换时,这步是关键哦,记着用map来构造你自己的匿名数组列表,匿名数组的第1个元素是最终需要的值,第2个元素是用于比较的值。

sort { $a->;[1] <=>; $b->;[1] } 对上1步中产生的匿名数组,按第2个元素进行sort,它返回sort后的匿名数组列表。

map { $_->;[0] } 对上1步中sort后的匿名数组,提取出第1个元素,也就是整行哦。

$str = join "/n", 把上步中的各行用"/n"连接起来,并赋值给$str。

也许你会说:“怎么这么麻烦呀?偶不想用这种方式。”那么,可用CPAN上的现成模块来代替:

use Sort::Fields;
@sorted = fieldsort [ 6, ''2n'', ''-3n'' ] @lines;

CPAN的模块文档很详细的,自己看看呀。

11. 重访高效sorting: Guttman-Rosler转换

考虑如下示例:

@dates = qw(2001/1/1 2001/07/04 1999/12/25);

你想按日期升序对它们进行排序,哪种方法最有效呢?

最直观的Schwartzian转换可以这样写:

@sorted = map { $_->;[0] }
      sort { $a->;[1] <=>; $b->;[1]
          or $a->;[2] <=>; $b->;[2]
          or $a->;[3] <=>; $b->;[3]
          }
      map { [ $_, split m</>; $_, 3 ] } @dates;

然而,更高效的Guttman-Rosler转换(GRT)这样写:

@sorted = map { substr $_, 10 }
      sort
      map { m|(/d/d/d/d)/(/d+)/(/d+)|;
          sprintf "%d-%02d-%02d%s", $1, $2, $3, $_
        } @dates;

本文作者说:

GRT方法难于编码,并且比Schwartzian转换更难阅读,所以我推荐仅在极端环境下使用GRT。使用大的数据源,perl 5.005_03和linux 2.2.14进行测试,GRT比Schwartzian转换快1.7倍。用perl 5.005_02和windows NT 4.0 SP6进行测试,GRT比Schwartzian快2.5倍。

文章出处:DIY部落(file:///G:/我的桌面/perl方法:sort函数%20,web技术文章,FrontPage,网页设计.htm)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值