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

时间:2010-10-12 14:37:09

标签: regex perl grep

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

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

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

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

任何见解都将受到赞赏。

6 个答案:

答案 0 :(得分: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 :(得分: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;
}

答案 2 :(得分:1)

对于这类问题,诀窍是不要扫描数组而不是必须。我认为Knuth写了一整本书。 :)通常情况下,我们会陷入这种情况,因为我们过于贴近我们先尝试的事情。

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

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;

当你不关心模式的哪个部分匹配时,这种事情就有效。

答案 3 :(得分:0)

  

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

不,不。如上所述,它什么都不打印。在严格打开的情况下,它会打印“全局符号”$ temp“需要显式包”。

修复那个明显的拼写错误并打开警告,它会两次打印“在打印中使用未初始化的值$ _”。

请不要浪费我们的时间,向我们展示无法编译的代码与您说的不相符。不要将代码重新键入此站点 - 剪切并粘贴您正在使用的实际代码。

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

#!/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;
}

但是可能有更有效的方法。

答案 4 :(得分:-1)

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

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

答案 5 :(得分:-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