转换为Perl

时间:2017-12-14 07:06:22

标签: perl subroutine

我有这个代码,在这种情况下使用给定列表提取名称:

我想在子程序中转换这段代码,我尝试过不同的方法,但它并没有给我我想要的东西。另一个问题是,如何在不使用foreach (@match){ push (@extract, $_)的情况下将所有结果(在本例中为Barney Rubble,Wilma Flinstone)添加到@match数组中?

#!/usr/bin/perl -w
use strict;
my @array1 = ( "Fred Flinstone", "Wilma Flinstone", "Barney Rubble", "Betty Rubble" );
my @list = ("Ba", "Wil");
my (@match, @extract);

for (@list){
    my $unit = $_;
    chomp $unit;

    @match = grep (/$unit/, @array1);

    foreach (@match){
        push (@extract, $_);
    }
}

foreach (@extract){
    print "$_\n";
}

2 个答案:

答案 0 :(得分:4)

#!/usr/bin/perl -w
use strict;

sub build_re { "(?:".( join '|', map quotemeta, @_ ).")" }

my @strings = ( "Fred Flinstone", "Wilma Flinstone", "Barney Rubble", "Betty Rubble" );
my @substrings = ( "Ba", "Wil" );

my $re = build_re(@substrings);
my @matches = grep /$re/, @strings;

注意:

  • 此代码包含一个sub(根据要求)。
  • 这种方法要快得多。
  • 此方法可修复重复问题。 (例如,它不像您的代码那样将William Bates添加到@matches两次。)
  • 这种方法很稳定。 (输出与输入的顺序相同。)
  • 此代码使用更合理的变量名称。
  

如何在不使用foreach (@match){ push (@extract, $_)的情况下将所有结果添加到@match数组?

foreach (@match) { push (@extract, $_); }

相当于

push @extract, @match;

答案 1 :(得分:0)

use strict;
use warnings;

sub multi_grep {
    my $checks = shift;
    my %seen;
    for my $check (@$checks) {
        ++$seen{$_} for grep $check, @_;
    }

    # This ensures we don't remove duplicates.
    # It also happens to make this approach stable.
    return grep $seen{$_}, @_;
}

my @array1 = ( "Fred Flinstone", "Wilma Flinstone", "Barney Rubble", "Betty Rubble" );
my @list = ( "Ba", "Wil" );  # Expected to be regex patterns.

my @matches = multi_grep(\@list, @array1);

注意:

  • 此代码将代码移动到子代码(根据请求)。
  • 此方法可修复重复问题。 (例如,它不像您的代码那样将William Bates添加到@matches两次。)
  • 这种方法很稳定。 (输出与输入的顺序相同。)