| |
咨询热线
- 免费咨询电话:
- 400-700-0056
- 800-810-0056
- 教学就业监督电话:
- 400-810-3016
- QQ在线咨询:
- 517589021

- 540118445

- 810143172

- MSN在线咨询:
- upadv01@hotmail.com
- upadv05@hotmail.com
- upadv06@hotmail.com
|
|
文章内容
-
清单 4. 函数使用循环
calculate_list($values); sub calculate_list { my ($list) = @_; foreach my $item (keys %{$values}) { $values->{$item}->{result} = ($item->{adda}+$item->{addb}); } }
更好的方式是在这种简单的计算中或者在简单的循环中使用 map:
map { $values->{$_}->{result} = $values->{$_}->{adda}+$values->{$_}->{addb} } keys %{$values};
还要记住的是,在循环中,每次反复都是在浪费时间,因此不要多次使用相同的循环,而是要尽量在一个循环中执行所有的操作。
排序 另外一种有关循环的通用操作是排序,特别是对 hash 表中的键值进行排序。在这个例子中嵌入对列表元素进行排序的操作是非常诱人的,如清单 5 所示。
清单 5. 不好的排序 my @marksorted = sort {sprintf('%s%s%s', $marked_items->{$b}->{'upddate'}, $marked_items->{$b}->{'updtime'}, $marked_items->{$a}->{itemid}) <=> sprintf('%s%s%s', $marked_items->{$a}->{'upddate'}, $marked_items->{$a}->{'updtime'}, $marked_items->{$a}->{itemid}) } keys %{$marked_items};
这是一个典型的复杂数据排序操作,在该例中,要对日期、时间和 ID 号进行排序,这是通过将数字连接在一个数字上,然后对其进行数字排序实现的。问题是排序操作要遍历列表元素,并根据比较操作上下移动列表。这是一种类型的排序,但是与我们已经看到的排序的例子不同,它对每次比较操作都调用 sprintf。每次循环至少执行两次,遍历列表需要执行的精确循环次数取决于列表最初排序的情况。例如,对于一个 10,000 个元素的列表来说,您可能会调用 sprintf 超过 240,000 次。
解决方案是创建一个包含排序信息的列表,并只生成一次排序域信息。参考清单 5 中的例子,我将这段代码改写为清单 6 的代码。
清单 6. 较好的排序 map { $marked_items->{$_}->{sort} = sprintf('%s%s%s', $marked_items->{$_}->{'upddate'}, $marked_items->{$_}->{'updtime'}, $marked_items->{$_}->{itemid}) } keys %{$marked_items}; my @marksorted = sort { $marked_items->{$b}->{sort} <=> $marked_items->{$a}->{sort} } keys %{$marked_items};
现在不需要每次都调用 sprintf,对 hash 表中的每一项,只需要调用一次该函数,就可以在 hash 表中生成一个排序字段,然后在排序时就可以使用这个排序字段了。排序操作只能访问排序字段的值。您可以将对包含 10,000 个元素的 hash 表的调用从 240,000 次减少到 10,000 次。这取决于最初对排序部分执行的操作,但是如果使用清单 6 中的方法,则可能节省一半的时间。
如果使用从数据库(例如 MySQL 或类似的数据库)查询的结果来构建 hash 表,并在查询中使用使用排序操作,然后按照这个顺序来构建 hash 表,那么就无需再次遍历这些信息来进行排序。
使用简短的逻辑 与排序相关的是如何遍历可选值列表。使用很多 if 语句耗费的时间可能会令人难以置信。例如,请参阅清单 7 中的代码。
清单 7. 进行选择 if ($userchoice > 0) { $realchoice = $userchoice; } elsif ($systemchoice > 0) { $realchoice = $systemchoice; } else { $realchoice = $defaultchoice; }
这段代码除了浪费篇幅之外,其结构也有两个问题。首先,从编程的观点来看,它从来不会检查变量值是否有效,如果激活警告信息,这就是要注意的一个因素。其次,只有在到达每个选项时,才会对每个选项进行检查,这是一种浪费,因为比较操作(尤其是对字符串进行比较操作)非常耗时。这两个问题都可以使用简短逻辑进行解决。
如果使用逻辑 || 操作符,Perl 就会使用后面的第一个真值,顺序从左到右取值。一旦发现一个有效值之后,它就不会继续处理其他值。另外,由于 Perl 正在寻找一个真值,因此它也可以忽略未定义的值,而不会抱怨这些值尚未定义。因此您可以将上面的代码重新改写成以下这样:
$realchoice = $userchoice || $systemchoice || $defaultchoice;
如果 $userchoice 值为真,那么 Perl 就不会查看其他变量。如果 $userchoice 为假(请参阅表 1),那么 Perl 就需要检查 $systemchoice 的值,依此类推,直到最后一个值,这个值通常都会被使用,不管它是真还是假。
1. $userchoice 值 值 逻辑值 负数 True 零 False 正数 True 空字符串 False 非空字符串 True 未定义的值 False 空列表(包括 hash 表) False 至少包含一个元素的列表(包括 hash 表) True 使用 AutoLoader 在执行 Perl 脚本过程中,最耗时的部分是将源代码编译成可以真正执行的字节码。对于一个没有使用外部模块的小脚本来说,这个过程可能需要几毫秒的时间。而启动一个包括很多外部模块的 Perl 脚本,就会增加时间。原因是 Perl 对模块的操作远远不止导入文本并使用相同的编译步骤运行这么简单。它会将 200 行的脚本快速转换为 10,000 或 20,000 行。结果是您增加了编译过程初始阶段的工作,在这时,脚本还不能执行任何任务。
点击:查看尚观ULP学员最新就业薪资待遇统计报告!
点击:了解尚观ULP-S专家课程(Linux主机、集群与大型数据库安全方向)
点击:了解尚观ULP-D专家课程(Linux内核、驱动与嵌入式开发方向)
填表获取 Linux、嵌入式、Oracle 技术资料
|