我是个新手。我有一个代码,其中变量在foreach循环期间加载了几个值。我想要做的是仅在该变量中对该变量执行某些操作。在perl中执行此操作的最有效方式是什么,因为我正在处理的数据非常大。
我的问题的一个简单例子是,说我有一系列我想要的水果
@fruits_i_like = qw (mango banana apple);
但是我在foreach循环中有一个$ fruit变量,它从一个包含所有不同类型水果的数据文件中获取水果的名称。我如何只选择@fruits_i_like数组中$ fruit的那些案例?
答案 0 :(得分:11)
Perl 5.10或更高版本?
use strict;
use warnings;
use 5.10.0;
my @fruits_i_like = qw/mango banana apple/;
my $this_fruit = 'banana';
if ( $this_fruit ~~ \@fruits_i_like ) {
say "yummy, I like $this_fruit!";
}
在5.10之前:
use strict;
use warnings;
my @fruits_i_like = qw/mango banana apple/;
my $this_fruit = 'banana';
if ( scalar grep $this_fruit eq $_, @fruits_i_like ) {
print "yummy, I like $this_fruit!\n";
}
缺点是解析整个数组以查找匹配项。这可能不是最佳选择,在这种情况下,您可以使用List::MoreUtils
'any()
,一旦匹配值就返回true,并且不会继续通过数组。
use strict;
use warnings;
use List::MoreUtils qw/any/;
my @fruits_i_like = qw/mango banana apple/;
my $this_fruit = 'banana';
if ( any { $this_fruit eq $_ } @fruits_i_like ) {
print "yummy, I like $this_fruit!\n";
}
快乐的黑客攻击!
答案 1 :(得分:10)
你可以使用这样的哈希:
my %h = map {$_ => 1 } @fruits_i_like;
if (exists $h{$this_fruit}) {
# do stuff
}
这是一个比较这种方式与mfontani解决方案的基准
#!/usr/bin/perl
use warnings;
use strict;
use Benchmark qw(:all);
my @fruits_i_like = qw/mango banana apple/;
my $this_fruit = 'banana';
my %h = map {$_ => 1 } @fruits_i_like;
my $count = -3;
my $r = cmpthese($count, {
'grep' => sub {
if ( scalar grep $this_fruit eq $_, @fruits_i_like ) {
# do stuff
}
},
'hash' => sub {
if (exists $h{$this_fruit}) {
# do stuff
}
},
});
输出:
Rate grep hash
grep 1074911/s -- -76%
hash 4392945/s 309% --
答案 2 :(得分:9)
这实际上是一个查找问题。在像@fruits_i_like
这样的散列中查找%fruits_i_like
的值会更快(这是O(1)与数组的O(n))。
使用以下操作将数组转换为哈希:
open my $data, '<', 'someBigDataFile.dat' or die "Unable to open file: $!";
my %wantedFruits;
@wantedFruits{@fruits_i_like} = (); # All fruits_i_like entries are now keys
while (my $fruit = <$data>) { # Iterates over data file line-by-line
next unless exists $wantedFruits{$fruit}; # Go to next entry unless wanted
# ... code will reach this point only if you have your wanted fruit
}