【发布时间】:2011-06-02 00:32:03
【问题描述】:
如果我有一个数组:
@int_array = (7,101,80,22,42);
如何在不遍历每个元素的情况下检查整数值 80 是否在数组中?
【问题讨论】:
如果我有一个数组:
@int_array = (7,101,80,22,42);
如何在不遍历每个元素的情况下检查整数值 80 是否在数组中?
【问题讨论】:
你不能没有循环。这就是数组的意义所在。您可以使用 grep 或 smartmatch 使用隐式循环,但仍然存在循环。如果您想避免循环,请改用(或另外)使用哈希。
# grep
if ( grep $_ == 80, @int_array ) ...
# smartmatch
use 5.010001;
if ( 80 ~~ @int_array ) ...
在使用智能匹配之前,请注意:
smartmatch 系列功能现在处于试验阶段
智能匹配,在 v5.10.0 中添加并在 v5.10.1 中进行了重大修改,一直是投诉点。尽管它有很多有用的方式,但它也被证明对于 Perl 的用户和实现者来说是有问题的和令人困惑的。关于如何最好地解决这个问题,已经提出了许多建议。很明显,smartmatch 几乎肯定会在未来改变或消失。不建议依赖其当前行为。
现在,当解析器看到 ~~、given 或 when 时会发出警告。要禁用这些警告,您可以将此行添加到适当的范围
【讨论】:
undef @hash{@array} 有效,但实际上并没有记录这样做。请改用@hash{@array} = ()。
CPAN 解决方案:使用List::MoreUtils
use List::MoreUtils qw{any};
print "found!\n" if any { $_ == 7 } (7,101,80,22,42);
如果您需要在同一个数组中进行 MANY MANY 查找,更有效的方法是将数组存储在哈希中一次,然后在哈希中查找:
@int_array{@int_array} = 1;
foreach my $lookup_value (@lookup_values) {
print "found $lookup_value\n" if exists $int_array{$lookup_value}
}
为什么要使用此解决方案而不是替代方案?
在 5.10 之前的 Perl 中无法使用智能匹配。根据 brian d foy]2 的这篇 SO 帖子,智能匹配是短路的,因此它与 5.10 的“任何”解决方案一样好。
grep 解决方案循环遍历 整个 列表,即使 1,000,000 个长列表的第一个元素匹配。 any 将在找到第一个匹配项时短路并退出,因此效率更高。原始海报明确表示“不遍历每个元素”
如果您需要进行大量查找,哈希创建的一次性沉没成本使哈希查找方法比其他任何方法更有效。见this SO post for details
【讨论】:
grep。
foreach 和last。
另一种检查数组中数字的方法:
#!/usr/bin/env perl
use strict;
use warnings;
use List::Util 'first';
my @int_array = qw( 7 101 80 22 42 );
my $number_to_check = 80;
if ( first { $_ == $number_to_check } @int_array ) {
print "$number_to_check exists in ", join ', ', @int_array;
}
【讨论】:
if ( grep /^80$/, @int_array ) {
...
}
【讨论】:
如果您使用的是 Perl 5.10 或更高版本,则可以使用 smart match 运算符 ~~:
my $found = (80 ~~ $in_array);
【讨论】: