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查询Mysql时返回字典结构的代码
Jun 18 Python
Python的ORM框架SQLObject入门实例
Apr 28 Python
用python登录Dr.com思路以及代码分享
Jun 25 Python
python检测是文件还是目录的方法
Jul 03 Python
Python中使用OpenCV库来进行简单的气象学遥感影像计算
Feb 19 Python
OpenCV+python手势识别框架和实例讲解
Aug 03 Python
Python3爬虫学习入门教程
Dec 11 Python
python求最大值最小值方法总结
Jun 25 Python
python requests更换代理适用于IP频率限制的方法
Aug 21 Python
Python object类中的特殊方法代码讲解
Mar 06 Python
keras CNN卷积核可视化,热度图教程
Jun 22 Python
python 6行代码制作月历生成器
Sep 18 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
4种PHP异步执行的常用方式
2015/12/24 PHP
PHP中-&gt;和=&gt;的含义及使用示例解析
2020/08/06 PHP
关于js注册事件的常用方法
2013/04/03 Javascript
javascript阻止浏览器后退事件防止误操作清空表单
2013/11/22 Javascript
jquery实现勾选复选框触发事件给input赋值
2015/02/01 Javascript
jfreechart插件将数据展示成饼状图、柱状图和折线图
2015/04/13 Javascript
JS实现统计复选框选中个数并提示确定与取消的方法
2015/07/01 Javascript
js 点击a标签 获取a的自定义属性方法
2016/11/21 Javascript
大白话讲解JavaScript的Promise
2017/04/06 Javascript
angular实现图片懒加载实例代码
2017/06/08 Javascript
详解在网页上通过JS实现文本的语音朗读
2019/03/28 Javascript
layui实现给某一列加点击事件
2019/10/26 Javascript
原生Vue 实现右键菜单组件功能
2019/12/16 Javascript
解决vue项目input输入框双向绑定数据不实时生效问题
2020/08/05 Javascript
python将图片文件转换成base64编码的方法
2015/03/14 Python
python3+mysql查询数据并通过邮件群发excel附件
2018/02/24 Python
完美解决Pycharm无法导入包的问题 Unresolved reference
2018/05/18 Python
Apache,wsgi,django 程序部署配置方法详解
2019/07/01 Python
python统计mysql数据量变化并调用接口告警的示例代码
2020/09/21 Python
Django Admin后台模型列表页面如何添加自定义操作按钮
2020/11/11 Python
Solid & Striped官网:美国泳装品牌
2019/06/19 全球购物
Linux如何命名文件--使用文件名时应注意
2012/01/22 面试题
房地产销售员的自我评价分享
2013/12/04 职场文书
企事业单位求职者的自我评价
2013/12/28 职场文书
企业员工培训感言
2014/02/26 职场文书
会展策划与管理专业求职信
2014/06/09 职场文书
公司应聘自荐书
2014/06/14 职场文书
学生顶撞老师的检讨书
2014/09/17 职场文书
小学教师师德师风自我剖析材料
2014/09/29 职场文书
雨花台导游词
2015/02/06 职场文书
仓库保管员岗位职责
2015/02/09 职场文书
《称赞》教学反思
2016/02/17 职场文书
心得体会该怎么写呢?
2019/06/27 职场文书
如何使用Python对NetCDF数据做空间相关分析
2021/04/21 Python
python简单验证码识别的实现过程
2021/06/20 Python
Web应用开发TypeScript使用详解
2022/05/25 Javascript