Perl排序:施瓦茨变换

给定一个数组a = (a1, a2, ... , an)和一个函数fn(),现在对数组(fn(a1), fn(a2), ... , fn(an))排序。

如果用下面的方法直接排序的话,会存在很多的对fn()重复计算的情况。如果函数fn()比较复杂,这种重复会显得更加突出。

施瓦茨变换就是为了解决这个对fn()重复计算问题,如下:

 
  
1 my @sorted =
2 map $_ -> [ 0 ] ,
3 sort { $b -> [ 1 ] <=> $a -> [ 1 ] }
4 map [ $_ , f( $_ ) ] ,
5 @original ;    

泛化一点:

 
  
1 my @sorted =
2 map $_ -> [ 0 ] ,
3 sort { SORT COMPARISON USING $a -> [ 1 ] AND $b -> [ 1 ] }
4 map [ $_ , EXPENSIVE FUNCTION OF $_ ] ,
5 @original ;
6  

举例:

 
  
1 # case insensitive sorting in alphabetical order
2   my @sorted =
3 map $_ -> [ 0 ] ,
4 sort { $a -> [ 1 ] cmp $b -> [ 1 ] }
5 map [ $_ , " \U$_ " ] ,
6 @original

在三级排序中使用施瓦茨变换:

 
  
1 # 首先用SOME FUNCTION排序,再用ANOTHER排序,最后用
2 # YET ANOTHER排序
3   my @sorted =
4 map $_ -> [ 0 ] ,
5 sort { SORT COMPARISON USING $a -> [ 1 ] AND $b -> [ 1 ] or
6 ANOTHER USING $a -> [ 2 ] AND $b -> [ 2 ] or
7 YET ANOTHER USING $a -> [ 3 ] AND $b -> [ 3 ] }
8 map [ $_ , SOME FUNCTION OF $_ , ANOTHER , YET ANOTHER ] ,
9 @original ;
10  

或者将每次计算的结果保存一下,这也避免了重复计算(举例用cmp做字符串比较):

 
  
1 @sorted = do {
2 my %fv ;
3 sort { ( $fv { $a } ||= f( $a ))
4 cmp
5 ( $fv { $b } ||= f( $b ))
6 }
7 @original
8 };

或者把用于cache的hash定义在do block外:

 
  
1 my %fv ;
2   @sorted =
3 sort { (fv{ $a } ||= f( $a ))
4 cmp
5 (fv{ $b } ||= f( $b ))
6 }
7 @original ;

或者事先把所有的fn()计算出来:

 
  
1 my %fv ;
2   @gv { @original } = map { fn( $_ ) } @original ;
3   @sorted = sort { $fv { $a } cmp $v { $b } } @original ;

或者用Memoize模块:

 
  
use Memoize;
memoize(
' fn ' );
@sorted = sort { fn( $a ) cmp fn( $b ) } @original ;

 

转载于:https://www.cnblogs.com/coldplayerest/archive/2010/02/16/1668828.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值