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 3中实现类型检查器的简单方法
Jul 03 Python
Django卸载之后重新安装的方法
Mar 15 Python
python实现拓扑排序的基本教程
Mar 11 Python
python实现定时提取实时日志程序
Jun 22 Python
初探利用Python进行图文识别(OCR)
Feb 26 Python
Python socket模块实现的udp通信功能示例
Apr 10 Python
Python图像处理模块ndimage用法实例分析
Sep 05 Python
Python Django框架防御CSRF攻击的方法分析
Oct 18 Python
python3实现单目标粒子群算法
Nov 14 Python
Python通过Pillow实现图片对比
Apr 29 Python
Python变量及数据类型用法原理汇总
Aug 06 Python
Python Sqlalchemy如何实现select for update
Oct 12 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
实现树状结构的两种方法
2006/10/09 PHP
一些PHP写的小东西
2006/12/06 PHP
PHP设计模式之调解者模式的深入解析
2013/06/13 PHP
PHP 超级全局变量相关总结
2020/06/30 PHP
PHP7 list() 函数修改
2021/03/09 PHP
Jquery Validation插件防止重复提交表单的解决方法
2010/03/05 Javascript
一样的table?不一样的table(可编辑状态table)
2012/09/19 Javascript
Javascript拓展String方法小结
2013/07/08 Javascript
jquery实现非叠加式的搜索框提示效果
2014/01/07 Javascript
jQuery图片切换插件jquery.cycle.js使用示例
2014/06/16 Javascript
JQuery做的一个简单的点灯游戏分享
2014/07/16 Javascript
JavaScript实现自动变换表格边框颜色
2015/05/08 Javascript
BootStrap智能表单实战系列(七)验证的支持
2016/06/13 Javascript
vue快捷键与基础指令详解
2017/06/01 Javascript
ES6之模版字符串的具体使用
2018/05/17 Javascript
css配合JavaScript实现tab标签切换效果
2018/10/11 Javascript
vue实现微信分享功能
2018/11/28 Javascript
JS通过ajax + 多列布局 + 自动加载实现瀑布流效果
2019/05/30 Javascript
Python itertools模块详解
2015/05/09 Python
python3 tkinter实现点击一个按钮跳出另一个窗口的方法
2019/06/13 Python
python实现桌面气泡提示功能
2019/07/29 Python
Python爬虫 批量爬取下载抖音视频代码实例
2019/08/16 Python
使用pytorch完成kaggle猫狗图像识别方式
2020/01/10 Python
python操作微信自动发消息的实现(微信聊天机器人)
2020/07/14 Python
Python xlrd/xlwt 创建excel文件及常用操作
2020/09/24 Python
HomeAway英国:全球领先的度假租赁在线市场
2020/02/03 全球购物
什么是lambda函数
2013/09/17 面试题
法学专业自我鉴定
2014/02/05 职场文书
自立自强的名人事例
2014/02/10 职场文书
电气工程自动化求职信
2014/03/14 职场文书
农业开发项目建议书
2014/05/16 职场文书
区长工作作风个人整改措施
2014/10/01 职场文书
2015年初中元旦晚会活动总结
2014/11/28 职场文书
2014大学生学生会工作总结
2014/12/19 职场文书
银行客户经理岗位职责
2015/04/09 职场文书
Go语言基础切片的创建及初始化示例详解
2021/11/17 Golang