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

   这篇文章主要介绍了Perl中著名的Schwartzian转换问题解决实现,本文详解讲解了Schwartzian转换涉及的排序问题,并同时给出实现代码,需要的朋友可以参考下

  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

时间: 2024-09-19 08:18:47

Perl中著名的Schwartzian转换问题解决实现的相关文章

Perl中捕获警告信息、异常信息并写入日志详解

  这篇文章主要介绍了Perl中捕获警告信息.异常信息并写入日志详解,本文分别给出了捕获警告--不处理.捕获警告--并转换成异常.捕获警告--并写入日志.捕获并写日志的完整例子等实用实例,需要的朋友可以参考下 虽然建议在每个Perl脚本和模块中开启警告,可是你又不想用户看到Perl发出的警告. 一方面你想在代码前面使用use warnings作为你的安全网,另一方面,通常警告会出现在屏幕上.多数情况下,客户不知道如何处理这些警告.如果幸运的话这些警告仅仅让客户惊讶一下,当然,不幸的是他们尝试着去

讲Perl中的本地时间与UNIX时间戳间相互转换的方法

  这篇文章主要介绍了讲Perl中的本地时间与UNIX时间戳间相互转换的方法,主要用到了Perl中的Date::Parse模块,需要的朋友可以参考下 当你的Perl脚本需要解决时间信息,这里有两种方法来表示和处理日期和时间.一种方法是易读的时间表示(例,"Sat Mar 14 10:14:05 EDT 2015"),另外一种是使用UNIX时间戳(也叫"新纪元时间"),这是从1970年1月1日到今所经过的时间秒数.每一种方法都有它自己的优劣势,取决于你的需要,也许也就

Perl中的真与假深入研究

  这篇文章主要介绍了Perl中的真与假深入研究,本文详细讲解了Perl中真值与假值的不同,需要的朋友可以参考下 Perl认为真值是自明的(self-evident), 表示任何事物的真值都可以计算.Perl以实用的方式来定义真值,即一个实体的真值取决于这个实体的类型.Perl总是乐观的认为:这个世界上真的东西远比假的东西多的多. Perl区别与任何其他计算机语言,Perl是语言学家创造的,而语言的意思离不开上下文语境,所以Perl中的真值都可以在标量(标量$与数组@类似于英文中的单数与复数,

Perl中的正则表达式介绍

正则表达式是 Perl 语言的一大特色,也是 Perl 程序中的一点难点,不过如果大家能够很好的掌握他,就可以轻易地用正则表达式来完成字符串处理的任务,当然在 CGI 程序设计中就更能得心应手了   感谢AKA及作者. Perl 中的正则表达式正则表达式的三种形式 正则表达式中的常用模式 正则表达式的 8 大原则       正则表达式是 Perl 语言的一大特色,也是 Perl 程序中的一点难点,不过如果大家能够很好的掌握他,就可以轻易地用正则表达式来完成字符串处理的任务,当然在 CGI 程序

oracle中 如何将拉丁文转换成中文

问题描述 oracle中 如何将拉丁文转换成中文 '???? 我也不知道这个拉丁文是什么意思,有没有哪位大神转换过啊,在线等 解决方案 这是拉丁文还是(乱码了)?确定这是拉丁文? 解决方案二: 这是拉丁文还是(乱码了)?确定这是拉丁文? 解决方案三: 这看上去是一种文字而不是乱码.什么意思嘛,你需要找翻译 解决方案四: oracle11汉字乱码的问题解决方法 鼠标右键"计算机"->"系统属性"->"高级系统设置"->"

Linux有问必答:Perl中本地时间和UNIX时间戳间相互转换

Linux有问必答:Perl中本地时间和UNIX时间戳间相互转换 问题: 在Perl语言中,我需要转换易读的日期和时间到对应的UNIX时间戳,反之亦然.你可以给我一些将日期及时间转换到UNIX时间戳的Perl代码例子吗?或者相反,转换UNIX时间戳到可读的日期和时间. 当你的Perl脚本需要解决时间信息,这里有两种方法来表示和处理日期和时间.一种方法是易读的时间表示(例,"Sat Mar 14 10:14:05 EDT 2015"),另外一种是使用UNIX时间戳(也叫"新纪元

Perl中的真与假深入研究_perl

Perl认为真值是自明的(self-evident), 表示任何事物的真值都可以计算.Perl以实用的方式来定义真值,即一个实体的真值取决于这个实体的类型.Perl总是乐观的认为:这个世界上真的东西远比假的东西多的多. Perl区别与任何其他计算机语言,Perl是语言学家创造的,而语言的意思离不开上下文语境,所以Perl中的真值都可以在标量(标量$与数组@类似于英文中的单数与复数, book 与 books的区别, 真值在现实世界中,应该就是单数,所以是标量)计算,除此之外,不会做任何类型的强制

Python中使用swapCase()方法转换大小写的教程

  这篇文章主要介绍了在Python中使用swapCase()方法转换大小写的教程,是Python入门中的基础知识,需要的朋友可以参考下 swapCase()方法返回所有可大小写,基于字符大小写交换字符串的一个副本. 语法 以下是swapCase()方法的语法: ? 1 str.swapcase(); 参数 NA 返回值 此方法返回其中所有基于大小写字符交换字符串的一个副本. 例子 下面的例子显示的swapCase()方法的使用. ? 1 2 3 4 5 6 7 #!/usr/bin/pytho

java中文件长度的转换

中文|转换 java中文件长度的转换 我们使用java.io.File对象创建一个具体的文件句柄,然后就可以通过这个对象 获取该文件的一些信息了, 但是在我们得到文件长度的时候,返回的是一个long类型的整数, 单位是byte,也就是字节.有时候当文件过大的时候,我们就需要转换成Mb或者 Gb.下面写了个函数实现这个功能: File objFile = new File("c:\\cqq.rar");long filesize=objFile.getLength(); static S