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中bisect的用法
Sep 23 Python
对python中数组的del,remove,pop区别详解
Nov 07 Python
Python模块的加载讲解
Jan 15 Python
Python计算一个点到所有点的欧式距离实现方法
Jul 04 Python
TensorFlow实现打印每一层的输出
Jan 21 Python
python中有函数重载吗
May 28 Python
python 密码学示例——凯撒密码的实现
Sep 21 Python
Python排序函数的使用方法详解
Dec 11 Python
Python Selenium库的基本使用教程
Jan 04 Python
Opencv中cv2.floodFill算法的使用
Jun 18 Python
Python中可变和不可变对象的深入讲解
Aug 02 Python
Python可变集合和不可变集合的构造方法大全
Dec 06 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
一个查看session内容的函数
2006/10/09 PHP
PHP面向对象程序设计之类常量用法实例
2014/08/20 PHP
php简单实现MVC
2015/02/05 PHP
PHP+MYSQL实现用户的增删改查
2015/03/24 PHP
php实现多城市切换特效
2015/08/09 PHP
PHP上传文件参考配置大文件上传
2015/12/16 PHP
PHP微信企业号开发之回调模式开启与用法示例
2017/11/25 PHP
开发 Internet Explorer 右键功能表(ContextMenu)
2013/07/03 Javascript
angular中使用路由和$location切换视图
2015/01/23 Javascript
javascript实现淡蓝色的鼠标拖动选择框实例
2015/05/09 Javascript
js控制元素显示在屏幕固定位置及监听屏幕高度变化的方法
2015/08/11 Javascript
基于BootStrap的Metronic框架实现页面链接收藏夹功能按钮移动收藏记录(使用Sortable进行拖动排序)
2016/08/29 Javascript
基于JavaScript实现选项卡效果
2017/07/21 Javascript
JavaScript实现多叉树的递归遍历和非递归遍历算法操作示例
2018/02/08 Javascript
解决Vue中引入swiper,在数据渲染的时候,发生不滑动的问题
2018/09/27 Javascript
Nginx设置为Node.js的前端服务器方法总结
2019/03/27 Javascript
详解微信小程序之提高应用速度小技巧
2020/01/07 Javascript
python插入排序算法的实现代码
2013/11/21 Python
python输入错误密码用户锁定实现方法
2017/11/27 Python
VSCode下配置python调试运行环境的方法
2018/04/06 Python
python经典趣味24点游戏程序设计
2019/07/26 Python
HTML5 Web 存储详解
2016/09/16 HTML / CSS
联想德国官网:Lenovo Germany
2018/07/04 全球购物
Pretty You London官网:英国拖鞋和睡衣品牌
2019/05/08 全球购物
NULL是什么,它是怎么定义的
2015/05/09 面试题
小学生新学期寄语
2014/01/19 职场文书
企业形象策划方案
2014/05/29 职场文书
安全目标管理责任书
2014/07/25 职场文书
推广普通话共筑中国梦演讲稿
2014/09/21 职场文书
兼职安全员岗位职责
2015/02/15 职场文书
农贸批发市场管理制度
2015/08/07 职场文书
html5移动端禁止长按图片保存的实现
2021/04/20 HTML / CSS
MySQL Shell的介绍以及安装
2021/04/24 MySQL
golang内置函数len的小技巧
2021/07/25 Golang
《LOL》“克隆大作战”久违归来 幻灵战队皮肤上线
2022/04/03 其他游戏
SONY AN-LP1 短波有源天线放大器图
2022/04/05 无线电