【问题标题】:How do I find all elements of one array that are not present in another array?如何找到一个数组中不存在于另一个数组中的所有元素?
【发布时间】:2015-09-30 13:39:24
【问题描述】:

我在研究时发现的答案指向使用grep,特别是因为数组不超过 20-40 个元素。

我有两个文件名数组,@allfiles@keepfiles。我想删除文件名仅存在于@allfiles 中的文件。 @allfiles 的元素比 @keepfiles 多。

我想使用类似的东西:

for(my $ii=0;$ii<=$allfilesSize-1; $ii++)
   {
    # if the current element of @allfiles is not in @keepfiles, delete the file
    unless(grep(@allfiles->[$ii],@keepfiles))
    {
        my $command = "del <value of @allfiles->[$ii]>";
        system($command);
    }
 }

我不知道如何编写grep 语句。 要么我不知道如何正确引用数组元素的值,要么不编写正则表达式,或者很可能两者兼而有之。还是有更好的方法来做到这一点?

【问题讨论】:

    标签: arrays regex perl grep


    【解决方案1】:

    您可以在 CPAN 上使用来自 Array::Utilsarray_minus 来做到这一点。

    use strict;
    use warnings;
    use Array::Utils 'array_minus';
    use Data::Printer;
    
    my @allfiles = ('a'..'z');
    my @keepfiles = qw(a e i o u);
    
    my @delete_files = array_minus(@allfiles, @keepfiles);
    
    p @delete_files;
    

    输出:

    [
        [0]  "b",
        [1]  "c",
        [2]  "d",
        [3]  "f",
        [4]  "g",
        [5]  "h",
        [6]  "j",
        [7]  "k",
        [8]  "l",
        [9]  "m",
        [10] "n",
        [11] "p",
        [12] "q",
        [13] "r",
        [14] "s",
        [15] "t",
        [16] "v",
        [17] "w",
        [18] "x",
        [19] "y",
        [20] "z"
    ]
    

    您也可以使用查找哈希,这是 Perl 中非常常见的习惯用法。您首先建立一个哈希,然后使用 exists 关键字检查是否存在密钥。

    use strict;
    use warnings;
    use Data::Printer;
    
    my @allfiles = ('a'..'z');
    my @keepfiles = qw(a e i o u);
    
    my %lookup = map { $_ => 1 } @keepfiles;
    my @delete_files = grep { ! exists $lookup{$_} && $_ } @allfiles;
    
    p @delete_files;
    

    输出同上。

    【讨论】:

      【解决方案2】:

      这样的事情应该可以工作。只需使用真正的数组,并将print 语句替换为您的system 命令。

      use warnings;
      use strict;
      
      my @all = qw(a b c d e f);
      my @some = qw(c f);
      
      for my $file (@all){
          if (! grep /^$file\z/, @some){
              print "$file\n";
          }
      }
      

      【讨论】:

      • 这样做效率很低 - grep 是一个循环结构,因此您对 @some 的迭代次数可能超出了您的需要。
      • 感谢@Sobrique 的反馈,我一直在寻找它,非常感谢。
      【解决方案3】:

      @simbabque 建议的两个变体并不完全相等。 差异是由于使用造成的 &amp;&amp; $_ 在第二个变体中的表达式 my @delete_files = grep { ! exists $lookup{$_} &amp;&amp; $_ } @allfiles; 中。

      据我了解,代码&amp;&amp; $_ 仅用于避免将大数组(@allfiles)中的0或''(空字符串)之类的值复制到输出数组(@delete_files)。虽然 Array::Utils::array_minus() 不提供这样的功能。 如果您省略代码&amp;&amp; $_,您将收到相同的变体。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-06
        • 2016-07-27
        • 1970-01-01
        • 2016-04-26
        • 2021-12-30
        相关资源
        最近更新 更多