首页 文章

如何确定数组中是否存在元素(perl)

提问于
浏览
10

我循环遍历一个数组,我想测试是否在另一个数组中找到了一个元素 .

在伪代码中,我想要做的是:

foreach $term (@array1) {
    if ($term is found in @array2) { 
        #do something here
    }
}

我已经得到了“foreach”和“在这里做了些什么”的部分......但是我为“如果术语在阵列中找到”测试所尝试的一切都不起作用......

我试过grep:

if grep {/$term/} @array2 { #do something }
# this test always succeeds for values of $term that ARE NOT in @array2

if (grep(/$term/, @array2)) { #do something }
# this test likewise succeeds for values NOT IN the array

我已经尝试了几种不同的“将数组转换为哈希”的方式,许多以前的帖子都指出这些方法非常简单容易......而且它们都没有用 .

我是perl的长期低级用户,我理解perl的基础知识,不明白所有花哨的混淆代码,包含我在interwebs上读到的99%的解决方案......我真的,真的,老老实实地欣赏代码中明确的任何答案,并提供代码正在做什么的逐步解释......

...我认真地不要理解$ _以及任何其他种类或类型的隐藏,理解或暗示的 Value ,变量或功能 . 如果任何示例或示例都包含以明确术语命名的所有变量和函数($ term而不是$ _),我将非常感激...并用注释描述代码正在做什么,所以我,在我所有的精神缺陷的荣耀中,可能希望有一天能够理解它 . 请 . :-)

...

我有一个现有的脚本使用'grep'有点成功:

$rc=grep(/$term/, @array);
if ($rc eq 0) { #something happens here }

但是我将那个完全相同的代码应用到我的新脚本中它并没有正确成功...即,当它测试$ term的值时,它“成功”(rc = 0),我知道该数组中不存在测试 . 我只是不明白 .

我在'旧'脚本和'新'脚本之间的'grep'方法的唯一区别在于我是如何构建数组的...在旧脚本中,我通过从文件中读入来构建数组:

@array=`cat file`;

而在新脚本中我把数组放在脚本本身(因为它很小)...像这样:

@array=("element1","element2","element3","element4");

怎么会导致grep函数的输出不同?它们都是沼泽标准阵列!我不明白!!!! :-(
################################################## ######################

附录......我的实际代码的一些说明或示例:

################################################## ######################
我试图匹配/找到/ grep的术语是一个单词元素,例如“word123” .

这个练习只是为了从一个充满垃圾的文件中找到一些重要信息的快速脏脚本,所以我跳过所有的细节(使用严格,警告,模块,子程序)选择......这不是'必须优雅,简单 .

我正在搜索的术语存储在一个变量中,该变量通过split实例化:

foreach $line(@array1) {
  chomp($line);  # habit

  # every line has multiple elements that I want to capture
  ($term1,$term2,$term3,$term4)=split(/\t/,$line);  

  # if a particular one of those terms is found in my other array 'array2'
  if (grep(/$term2/, @array2) { 
    # then I'm storing a different element from the line into a 3rd array which eventually will be outputted
    push(@known, $term1) unless $seen{$term1}++;
  }
}

看到grep在那里?它没有正常工作......它对于$ term2的所有值都取得了成功,即使它绝对不在array2中... array1是一个几千行的文件 . 我在这里调用$ term2的元素是一个离散项,可以是多行,但在任何给定行中都不会重复(或者是较大字符串的一部分) . Array2是我需要“过滤”输出的几十个元素 .

...

我刚刚尝试了以下建议之一:

if (grep $_ eq $term2, @array2)

这个grep对于$ term2的所有值都失败了...我得到grep的全部或全部响应...所以我想我需要停止使用grep . 尝试其中一种哈希解决方案......但我真的可以使用更多的解释和澄清 .

7 回答

  • 5

    这应该工作 .

    #!/usr/bin/perl
    use strict;
    use warnings;
    
    my @array1 = qw/a b c d e f g h/;
    my @array2 = qw/a c e g z/;
    
    for my $term (@array1) {
        if (grep $_ eq $term, @array2) {
            print "$term found.\n";
        }
    }
    

    输出:

    a found.
    c found.
    e found.
    g found.
    
  • 0

    下面的示例可能会有所帮助,它会尝试查看@my_array中是否存在@array_sp中的任何元素:

    #! /usr/bin/perl -w
    
    @my_array = qw(20001 20003);
    
    @array_sp = qw(20001 20002 20004);
    print "@array_sp\n";
    
    foreach $case(@my_array){
        if("@array_sp" =~ m/$case/){
        print "My God!\n";
        }
    
    }
    

    使用模式匹配可以解决这个问题希望它有助于-QC

  • 2

    这是在perlfaq . 一个快速的方法是

    my %seen;
    $seen{$_}++ for @array1;
    for my $item (@array2) {
        if ($seen{$item}) {
            # item is in array2, do something
        }
    }
    

    如果字母大小写不重要,您可以使用 $seen{ lc($_) } 设置键并使用 if ($seen{ lc($item) }) 进行检查 .

    ETA:

    使用已更改的问题:如果任务是将 @array2 中的单个单词与 @array1 中的整行匹配,则任务更复杂 . 由于标点符号和其他类似的东西,尝试拆分行并匹配哈希键可能是不安全的 . 因此,正则表达式解决方案可能是最安全的 .

    除非 @array2 非常大,否则你可能会这样做:

    my $rx = join "|", @array2;
    for my $line (@array1) {
        if ($line =~ /\b$rx\b/) {  # use word boundary to avoid partial matches
            # do something
        }
    }
    

    如果 @array2 包含元字符,例如 *?+| ,则必须确保它们被转义,在这种情况下,您可以执行以下操作:

    my $rx = join "|", map quotemeta, @array2;
    # etc
    
  • 0

    您的“实际代码”甚至不应该编译:

    if (grep(/$term2/, @array2) {
    

    应该:

    if (grep (/$term2/, @array2)) {
    

    您的代码中有不 balancer 的括号 . 您可能还会发现使用grep与对其参数(数组)进行操作的回调(代码引用)更容易 . 它有助于保持括号不会模糊在一起 . 但这是可选的 . 这将是:

    if (grep {/$term2/} @array2) {
    

    你可能想要使用严格;并使用警告; grab 这样的问题 .

  • 1

    如果您使用的是5.10或更高版本,则可以使用(臭名昭着的)“智能匹配”运算符:

    #!/usr/bin/perl
    use strict;
    use warnings;
    
    my @array1 = qw/a b c d e f g h/; 
    my @array2 = qw/a c e g z/; 
    
    print "a in \@array1\n" if 'a' ~~ @array1;
    print "z in \@array1\n" if 'z' ~~ @array1;
    print "z in \@array2\n" if 'z' ~~ @array2;
    

    示例非常简单,但如果您需要,也可以使用RE . 我应该补充一点,不是每个人都喜欢~~因为有一些歧义,嗯,“没有文档的功能” . 虽然应该可以 .

  • 9
    #!/usr/bin/perl
    
    @ar = ( '1','2','3','4','5','6','10' );
    @arr = ( '1','2','3','4','5','6','7','8','9' ) ;
    
    foreach $var ( @arr ){
        print "$var not found\n " if ( ! ( grep /$var/, @ar )) ;
    }
    
  • 6

    模式匹配是匹配元素的最有效方式 . 这样就可以了 . 干杯!

    print "$element found in the array\n" if ("@array" =~ m/$element/);
    

相关问题