查找与第二个数组的元素匹配的数组元素

时间:2015-03-20 09:47:38

标签: arrays perl data-structures

我有两个数组@uarts@txd,看起来像这样

@uarts = qw(uart_1 uart_10 uart_3 uart_9 ); 
@txd = qw(PIO_uart_1 PIO_2_uart_1 PIO_uart_3 PIO_uart_10 PIO_uart_5 PIO_uart_9 PIO_uart_7);

我想只从@txd中提取包含@uarts的任何元素的元素。我为它编写的代码如下,但不起作用。

my @array;
for (my $i = 0 ; $i <= $#uarts ; $i++) {
  @array = grep { $_ =~ /$uarts[$i]/ } (@txd);
  print "@array\n";
}

4 个答案:

答案 0 :(得分:5)

我必须诚实。我认为mapgrep都非常烦人,因为如果你不熟悉perl - steer clear。他们并没有获得太多 - 他们看起来就像他们降低了代码的复杂性一样,但这是因为grep的循环是隐含的。所以你所做的就是让你的代码更难以理解。

另外 - 我真的不喜欢for循环的样式 - 它的几乎在perl中总是多余的 - 在上面的例子中,是你引用的唯一元素是当前的(如果您正在访问&#39; next&#39;或之前的&#39;元素,那就不一样了)。

因此展开它:

foreach my $uart ( @uarts ) {
    foreach my $PIO ( @txd ) {
        if ( $PIO =~ m/$uart/ ) { 
            print "$PIO matches $uart\n";
        }
     }
 }

注意:这不会进行任何类型的唯一性测试,因此如果发生多次匹配,您将获得欺骗。

哦,然后开启use strict;use warnings;。你的数组声明是错误的。

my @uarts = qw ( uart_1 uart_10 uart_3 uart_9 );
my @txd   = qw ( PIO_uart_1 PIO_2_uart_1 PIO_uart_3 PIO_uart_10
                 PIO_uart_5 PIO_uart_9PIO_uart_7
);

我也会指出 - 你已经将@array限制在你的循环之外,这可能意味着想要保留它。但是,然后通过分配grep的输出来破坏每次迭代。

我建议您在循环中定位@array,或者查看push / popshift / unshift作为添加和删除的方法现有数组中的元素。

答案 1 :(得分:3)

您的代码&#34;工作&#34;就目前而言。你应该总是说出你的意思&#34;不工作&#34;

我认为问题在于您的代码正如您所描述的那样完全。它找到&#34;来自@txd的那些元素,其中包含@uarts&#34; 的任何元素,而我认为您需要那些结束的元素 @uarts中的任何字符串。

因为它代表了你的节目输出

PIO_uart_1 PIO_2_uart_1 PIO_uart_10
PIO_uart_10
PIO_uart_3
PIO_uart_9

所以在检查uart_1时,它会找到PIO_uart_10,因为前者是后者的子串。要使用给定的uart字符串查找 end 的元素,您只需要向正则表达式添加行结束锚点,使其成为

@array = grep { $_ =~ /$uarts[$i]$/ } (@txd)

将输出更改为

PIO_uart_1 PIO_2_uart_1
PIO_uart_10
PIO_uart_3
PIO_uart_9

我希望你想要的是什么?

但它可以写得更好一点。除非你特别需要索引,否则最好循环遍历数组的内容,并且@array不需要是一个全局变量(并且它可以更好地构建一个)所以这对你有用

use strict;
use warnings;

my @uarts = qw(uart_1 uart_10 uart_3 uart_9 ); 
my @txd = qw(PIO_uart_1 PIO_2_uart_1 PIO_uart_3 PIO_uart_10 PIO_uart_5 PIO_uart_9 PIO_uart_7);

for my $uart ( @uarts ) {
  my @matches = grep /$uart\z/, @txd;
  print "@matches\n";
}

<强>输出

PIO_uart_1 PIO_2_uart_1
PIO_uart_10
PIO_uart_3
PIO_uart_9

答案 2 :(得分:1)

您只需将@array = grep{$_=~ /$uarts[$i]/}(@txd);更改为push @array, grep{$_=~ /$uarts[$i]/}(@txd);即可修复您的代码。

但是,如何做到这一点的有效和有效的方法是准备匹配的正则表达式,并在O(N+M)而不是O(N*M)中进行。

use strict;
use warnings;

my @uarts = qw(uart_1 uart_10 uart_3 uart_9);
my @txd
    = qw(PIO_uart_1 PIO_2_uart_1 PIO_uart_3 PIO_uart_10 PIO_uart_5 PIO_uart_9 PIO_uart_7);

my @array = do {
    my $re = join '|', map quotemeta, @uarts;
    $re = qr/$re/;
    grep /$re/, @txd;
};

print "@array\n";

答案 3 :(得分:-3)

@uarts =(uart_1,uart_10,uart_3,uart_9 ); 
@txd =(PIO_uart_1,PIO_2_uart_1,PIO_uart_3,PIO_uart_10,PIO_uart_5,PIO_uart_9,PIO_uart_7);
my @array;
for(my $i=0;$i<=$#uarts;$i++ )
{
    @array=grep{$_=~/$uarts[$i]/}(@uarts);
    print "@array\n";
}

<强>输出

uart_1 uart_10
uart_10
uart_3
uart_9