免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4909 | 回复: 8
打印 上一主题 下一主题

[zt] 高效排序之施瓦茨转换 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-08-30 16:52 |只看该作者 |倒序浏览

有人在Perl邮件列表上提了个问题,要求对如下数组的内容按指定规则进行排序:

my @array = qw(c r v vr tr re c.p[1] c.p[3] c.p[2] c.p[4] c.p[7]
c.p[6] c.p[5] c.p[8] c.t[1] c.t[3] c.t[2]);
I only want to sort the elements that have a numeric value inside the braces so that all the other elements have their original index preserved.

简言之,对@array数组的内容,按c.p[N], c.t[N]这里的N值进行升序排序,其他元素位置不变,要求输出形式如下:
c r v vr tr re c.p[1] c.p[2] c.p[3] c.p[4] c.p[5] c.p[6] c.p[7] c.p[8] c.t[1] c.t[2] c.t[3]

原提问者自己提到了施瓦茨转换,一种排序算法。但其他回答者认为这个不好用施瓦茨转换来做。
正好我对这种排序方法很熟悉,花了2分钟时间就写出来了:

        1.        my @new = map { $_->[0] }
        2.            sort { $a->[1]->[0] cmp $b->[1]->[0] or
        3.            $a->[1]->[1] <=> $b->[1]->[1] }
        4.            map {[$_,[ $_=~/\.(.+)\[(\d+)\]/ ]]}
        5.            @array;

现在@new数组就包含了排序后的内容,输出的结果是提问者所需要。
这种排序法在Perl里要倒着看,从第5行看到第1行(如果用ruby实现,就正着看,因为ruby的数组是个对象,map, sort是对象方法,从左往右调用)。

第5行是原始数组,第4行的map方法针对原始数组再产生一个临时数组,第2-3行的sort方法针对这个临时数组,按指定规则进行排序,
排序的结果又是一个临时数组,第1行的map从最后产生的临时数组里,提取出所需要的值,就是我们想要的结果。

施瓦茨转换是Perl黑客Randal L. Schwartz发明的,维基上有详细介绍:
http://en.wikipedia.org/wiki/Schwartzian_transform

论坛徽章:
0
2 [报告]
发表于 2012-08-30 17:05 |只看该作者
乍一看,只觉得为了应付数据的特点而map出了一个新的数据结构方便排序而已,倒是没看到所谓的高效之处。
我再去wiki上仔细读一下吧

论坛徽章:
0
3 [报告]
发表于 2012-08-30 17:14 |只看该作者
哈哈 wiki里的Efficiency analysis分析的很清楚了,多谢仙子分享,虽然平时可能写过类似的形式,但都没意识到这已经是一个很著名的 Perl programming idiom 啦

论坛徽章:
78
双子座
日期:2013-10-15 08:50:09天秤座
日期:2013-10-16 18:02:08白羊座
日期:2013-10-18 13:35:33天蝎座
日期:2013-10-18 13:37:06狮子座
日期:2013-10-18 13:40:31双子座
日期:2013-10-22 13:58:42戌狗
日期:2013-10-22 18:50:04CU十二周年纪念徽章
日期:2013-10-24 15:41:34巨蟹座
日期:2013-10-24 17:14:56处女座
日期:2013-10-24 17:15:30双子座
日期:2013-10-25 13:49:39午马
日期:2013-10-28 15:02:15
4 [报告]
发表于 2012-08-30 17:17 |只看该作者
c r v vr tr re这些也顺带排序了,如果最后再加个c,估计就不是想要的了

论坛徽章:
0
5 [报告]
发表于 2012-08-30 20:56 |只看该作者
yybmsrs 发表于 2012-08-30 17:17
c r v vr tr re这些也顺带排序了,如果最后再加个c,估计就不是想要的了


正如楼上所担心,我给扩展了一下
  1. my @array = qw(c r v vr tr re c.p[1] c.p[3] c.p[2] d c.p[4] c.p[7] c.p[6] c.p[5] c.p[8] c.t[1] c.t[3] c.t[2]);

  2. my @maps =  map { [ $_ , [ $_ =~ /[.](\w)\[(\d)\]/ ] ] }@array;
  3. my @sort = sort { $a->[1]->[0] cmp $b->[1]->[0]
  4.                   or
  5.                   $a->[1]->[1] <=> $b->[1]->[1]}
  6.            grep { @{$_->[1]} } @maps;

  7. my $i = 0;
  8. my @new  =  map { @{$_->[1]} ? $sort[$i++]->[0] : $_->[0] }@maps;

  9. print "@new\n";
复制代码

论坛徽章:
0
6 [报告]
发表于 2012-08-30 21:14 |只看该作者
回复 5# kk861123


    代码帝,实践帝,每次看你帖子总是代码。。

论坛徽章:
0
7 [报告]
发表于 2012-08-30 21:25 |只看该作者
回复 6# sjdy521

{:3_185:}
   

论坛徽章:
2
CU大牛徽章
日期:2013-04-17 11:46:28CU大牛徽章
日期:2013-04-17 11:46:39
8 [报告]
发表于 2012-08-30 21:51 |只看该作者
想到、做到

论坛徽章:
5
丑牛
日期:2014-01-21 08:26:26卯兔
日期:2014-03-11 06:37:43天秤座
日期:2014-03-25 08:52:52寅虎
日期:2014-04-19 11:39:48午马
日期:2014-08-06 03:56:58
9 [报告]
发表于 2013-12-11 17:49 |只看该作者
仔细读一下这高效{:2_172:}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP