如何从 Perl 数组中选择某些元素?

问题描述 投票:0回答:6

我想搜索一个数组中与另一个数组中的元素具有相同起始字符集的所有元素。说清楚一点:

@array = ("1a","9","3c");
@temp =("1","2","3");

我只想打印 1a 和 3c。当我尝试使用以下程序时,它会打印出数组中的所有元素,而不是我想要的两个:

foreach $word (@temp)
{
    if( grep /^$word/ , @array) 
    {
        print $_;
    }
}
regex perl grep
6个回答
3
投票

这个答案将满足OP的要求,并通过使用哈希查找防止在屏幕上打印任何重复项。

#!/usr/bin/perl

use strict;
use warnings;

my @array = ("1a","9","3c","3c");
my @temp =("1","2","3");

my %dups_hash;

for my $w (@temp) {
    my ($match) = grep /^$w/, @array;

    # Need to check if $match is defined before doing the hash lookup.
    # This suppresses error messages for uninitialized values; if defined($match) is
    #  false, we short circuit and continue in the loop.
    if(defined($match) && !defined($dups_hash{$match})) {
        print $match;
    }
}

1
投票

如果你想两两匹配元素,可以这样做:

for my $i (0..$#array) {
    print $array[$i], "\n" if $array[$i] =~ /^$temp[$i]/
}

否则你可以使用 grep:

for my $i (0..$#array) {
    print "$array[$i]\n" if grep /^$temp[$i]/, @array;
}

1
投票

对于这类问题,诀窍是不要扫描数组超过必要的次数。我认为高德纳为此写了一整本书。 :) 通常,我们会陷入这些情况,因为我们过于执着于我们首先尝试的事情。

您可以根据要搜索的所有模式构造一个正则表达式,然后扫描数组一次:

use Regexp::Assemble;

my @array = qw( 1a 9 3c );
my @temp  = qw( 1 2 3 );

my $ra = Regexp::Assemble->new;
$ra->add( @temp );

my $pattern = $ra->re;
print "pattern is [$pattern]\n";

print join ' ', grep /\A$pattern/ , @array;

当你不关心模式的哪一部分匹配时,只要它匹配就可以了。


0
投票

当我尝试使用以下内容时 程序打印出所有元素 在数组中而不是两个我 想要。

不,没有。正如所写,它什么也不打印。当严格打开时,它会打印“全局符号“$temp”需要显式包”。

修复了明显的拼写错误并打开警告,它会打印“Use of uninitialized value $_ in print”两次。

您的问题的解决方案将类似于:

#!/usr/bin/perl

use strict;
use warnings;

my @array = ("1a","9","3c");
my @temp =("1","2","3");

foreach my $word (@temp) {
  print grep /^$word/ , @array;
}

但是可能有更有效的方法来做到这一点。


-1
投票
map { print "$_\n" } grep { my $a = $_; grep {$a =~ /^$_/} @temp } @array

基本上,外部

grep
选择
@temp
中的 1 个或多个元素与内部正则表达式匹配的元素 - 也就是说,它选择以
@temp 中的一个(或多个)元素开头的所有元素
.


-1
投票

如果 grep 返回空列表,避免出现空行:

#!/usr/bin/perl
use strict;
use warnings;
use 5.10.1;

my @array = qw(1a 9 3c 1g);
my @temp =(1, 2, 3);
foreach my $word(@temp) {
  my @l = grep{/^$word/}@array;
  say "@l" if @l;
}

输出:

1a 1g
3c
© www.soinside.com 2019 - 2024. All rights reserved.