Perl中著名的Schwartzian转换问题解决实现


Posted in Python onJune 02, 2015

Perl中著名的Schwartzian转换,其产生背景主要涉及到排序问题:
比如说,根据文件名以字母顺序排序,代码如下:

use strict;  

use warnings;  

   

my @files = glob "*.xml";          #perl中文件操作符glob提供相当于shell中的通配符的功能  

my @sorted_files = sort @files;    #sort(),排序,默认是字母顺序排序

比如说,根据文件名长度排序,其代码如下:
use strict;  

use warnings;  

  

#length求长度。 太空船操作符<=>,默认变量是$a,$b,返回值为-1,0,1分别表示大于,==,小于。 sort进行排序  

my $files = ".xml";  

my @sorted_length = sort { length($a) <=> length($b) } @files; 

上面的两种情况,对很多文件操作来说,速度还不算慢,如果是下面这种情况。
比如说:要批量比较文件大小,其代码如下:
use strict;  

use warnings;  

   

my @files     = glob "*.xml";     

my @sort_size = sort { -s $a <=> -s $b } @files;  #比较大小 

上面的代码设计到三重(次)操作:
1. 从硬盘上获取文件大小(-s $b)
2. 比较文件大小(太空船操作)
3. 对其进行排序(sort操作)
考虑到要比较$a,$b大小时,要从硬盘中获取两次,所以次数是6次!也就是说,如果有1万个文件,总共是6万次。
其算法复杂度是: n*long(n),考虑到后两项(比较文件大小,进行排序)必然要进行的操作,但第一项却可以降低!
即一次性从硬盘中读取所有文件大小,将其放置到Perl中的默认的变量,并存储到内存中!于是又下面算法实现:
use strict;  

use warnings;  

  

my @files = glob "*.xml";  

  

my @unsorted_pairs = map  { [$_, -s $_] } @files;  

my @sorted_pairs   = sort { $a->[1] <=> $b->[1] } @unsorted_pairs;  

my @sorted_files   = map  { $_->[0] } @sorted_pairs; 

看上去比较复杂,分三个步骤解释下:
第一步:遍历文件列表,对每个文件创建一个数组引用。数组引用包含两个元素:
       第一个是文件名($_),第二个是文件大小(-s $_)。这样,处理每个文件只访问一次磁盘。
第二步:对二维数组排序。因比较文件大小,所以需取元素[1],比较它们的值。得到另一个二维数组。
第三步:丢掉文件大小元素,创建一个只含文件名的列表。完成目标!
上面的代码使用了两个临时数组,但这并不是必须的。我们可以一个语句就能完成所有的工作。为了达到目的,需要按照“数据从右流向左”的原理反转句子顺序,不如果将每个句子放在单独一行,并且留出足够的空间,我们依然可以写出可读性高的代码。
my @quickly_sorted_files =  

    map  { $_->[0] }  

    sort { $a->[1] <=> $b->[1] }  

    map  { [$_, -s $_] }  

    @files; 

这就是以Randal L. Schwartz命名的Schwartzian转换,对数据量特多的情况下,其速度要比前者快数倍!
下面写了小程序,包括在生成1万个xml文件,在两种情况下,完整代码如下:
#!/usr/bin/perl -w  

use strict;  

use warnings;  

use autodie;  

use v5.10;  

  

######################################  

###  创建要比较的10,000个.xml文件 ###  

######################################  

my $profix = ".xml";  

  

foreach my $num (1..10000) {  

    open(my $fh, '>', $num . $profix) || die "Can not create the file: $!\n";  

    print $fh "This is file size testing!";  

}  

  

print "All the 10_1000 files created! \n";  

  

  

######################################  

### 常规转换:      遍历20次       ###  

######################################  

my $t1  = time();  

  

foreach (1..20){   

    my @files     = glob "*.xml";  

    my @sorted    = sort { -s $a <=> -s $b } @files;  

}  

  

say "常规算法需要时间: => ", time()- $t1;  

  

  

######################################  

### Schwartzian转换: 遍历20次     ###  

######################################  

my $t2  = time();  

  

foreach (1..20){   

    my @files = glob "*.xml";  

        my @sorted =   

            map  {$_->[0]}  

            sort {$a->[1] <=> $b->[1]}  

            map  {[$_, -s $_]}  

       @files;  

} 
say "Schwartzian算法需要时间: => ", time()- $t2; 

输出结果:
All the 10_1000 files created!
常规算法需要时间:          => 185
Schwartzian算法需要时间: => 115

Python 相关文章推荐
python cookielib 登录人人网的实现代码
Dec 19 Python
python类中super()和__init__()的区别
Oct 18 Python
python 线程的暂停, 恢复, 退出详解及实例
Dec 06 Python
pandas值替换方法
Jul 10 Python
python3.6使用urllib完成下载的实例
Dec 19 Python
使用python opencv对目录下图片进行去重的方法
Jan 12 Python
python使用phoenixdb操作hbase的方法示例
Feb 28 Python
python2.7使用plotly绘制本地散点图和折线图
Apr 02 Python
python程序快速缩进多行代码方法总结
Jun 23 Python
Python类如何定义私有变量
Feb 03 Python
Python实现猜年龄游戏代码实例
Mar 25 Python
Python实现UDP程序通信过程图解
May 15 Python
python通过ssh-powershell监控windows的方法
Jun 02 #Python
Python lxml模块安装教程
Jun 02 #Python
Python脚本文件打包成可执行文件的方法
Jun 02 #Python
python统计cpu利用率的方法
Jun 02 #Python
Python2.x中文乱码问题解决方法
Jun 02 #Python
python实现的守护进程(Daemon)用法实例
Jun 02 #Python
Python中使用ElementTree解析XML示例
Jun 02 #Python
You might like
php str_replace的替换漏洞
2008/03/15 PHP
解析PHPExcel使用的常用说明以及把PHPExcel整合进CI框架的介绍
2013/06/24 PHP
php获取QQ头像并显示的方法
2014/12/23 PHP
PHP XML和数组互相转换详解
2016/10/26 PHP
Laravel实现ORM带条件搜索分页
2019/10/24 PHP
greybox——不开新窗口看新的网页
2007/02/20 Javascript
javascript 出生日期和身份证判断大全
2008/11/13 Javascript
ExtJs的Date格式字符代码
2010/12/30 Javascript
select标记美化--JS式插件、后期加载
2013/04/01 Javascript
Jquery.Form 异步提交表单的简单实例
2014/03/03 Javascript
SeaJS入门教程系列之使用SeaJS(二)
2014/03/03 Javascript
js实现汉字排序的方法
2015/07/23 Javascript
JavaScript的面向对象编程基础
2015/08/13 Javascript
基于jQuery实现表格的排序
2016/12/02 Javascript
Angularjs 实现移动端在线测评效果(推荐)
2017/04/05 Javascript
JavaScript实现简单动态进度条效果
2018/04/06 Javascript
微信小程序实现图片上传放大预览删除代码
2020/06/28 Javascript
Vue2 监听属性改变watch的实例代码
2018/08/27 Javascript
angularJs使用ng-repeat遍历后选中某一个的方法
2018/09/30 Javascript
单页面vue引入百度统计的使用方法示例详解
2018/10/13 Javascript
iView框架问题整理小结
2018/10/16 Javascript
详解ES6中的Map与Set集合
2019/03/22 Javascript
详解Vue 数据更新了但页面没有更新的 7 种情况汇总及延伸总结
2020/05/28 Javascript
python安装numpy&amp;安装matplotlib&amp; scipy的教程
2017/11/02 Python
解决Pytorch 训练与测试时爆显存(out of memory)的问题
2019/08/20 Python
关于numpy中eye和identity的区别详解
2019/11/29 Python
Python用Jira库来操作Jira
2020/12/28 Python
Opencv 图片的OCR识别的实战示例
2021/03/02 Python
英国卫浴商店:Ergonomic Design
2019/09/22 全球购物
美国基督教约会网站:ChristianCafe.com
2020/02/04 全球购物
心理健康教育制度
2014/01/27 职场文书
情况说明书格式范文
2014/05/06 职场文书
2014领导班子正风肃纪思想汇报
2014/09/18 职场文书
市语委办2016年第十九届“推普周”活动总结
2016/04/05 职场文书
python如何进行基准测试
2021/04/26 Python
Windows Server 2019 域控制器安装图文教程
2022/04/28 Servers