Perl:查找变量的值是否与数组中的值匹配

sfa*_*tor 7 regex arrays perl

我是个新手.我有一个代码,其中变量在foreach循环期间加载了几个值.我想要做的是仅在该变量中对该变量执行某些操作.在perl中执行此操作的最有效方法是什么,因为我正在处理的数据非常大.

我的问题的一个简单例子是,我说我想要一系列水果

@fruits_i_like = qw (mango banana apple);
Run Code Online (Sandbox Code Playgroud)

但是我在foreach循环中有一个$ fruit变量,它从一个包含所有不同类型水果的数据文件中获取水果的名称.我如何只选择@fruits_i_like数组中$ fruit的那些案例?

mfo*_*ani 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!";
}
Run Code Online (Sandbox Code Playgroud)

在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";
}
Run Code Online (Sandbox Code Playgroud)

缺点是整个数组被解析以找到匹配.这可能不是最好的选择,在这种情况下你可以使用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";
}
Run Code Online (Sandbox Code Playgroud)

快乐的黑客!


Tot*_*oto 10

您可以使用这样的哈希:

my %h = map {$_ => 1 } @fruits_i_like;
if (exists $h{$this_fruit}) {
    # do stuff
}
Run Code Online (Sandbox Code Playgroud)

这是一个比较这种方式与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
        }
    },
});
Run Code Online (Sandbox Code Playgroud)

输出:

          Rate grep hash
grep 1074911/s   -- -76%
hash 4392945/s 309%   --
Run Code Online (Sandbox Code Playgroud)

  • 如果你为此目的创建%h,它不应该成为基准测试的一部分吗? (3认同)
  • @ØyvindSkaar:我不这么认为,因为OP希望多次匹配水果.%h仅创建一次并多次使用.它与grep解决方案不同,grep解决方案是针对每种不同的水果进行的. (3认同)

Zai*_*aid 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
}
Run Code Online (Sandbox Code Playgroud)