• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

Perl排序:施瓦茨变换

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

给定一个数组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;

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap