首页 > 解决方案 > 比较两个数组并找出差异

问题描述

我需要比较两个数组并获得差异。

背景:

第一个数组将列出文件夹中的文件。

第二个数组将读取文件的内容并存储在数组中。

第一个数组的输出将是

a
b
c
d
e

第二个数组的输出将是

a
b
c
e

我如何比较那些有差异的 2 个数组?我想要的结局输出是

d

这是代码:

#!/usr/bin/perl

use strict;
use warnings;

my $list  = "experiment.sv";
my $path  = "../../../folder1/";
my $filelist;

open ( OUTFILE, ">output.txt" );
main ();
close OUTFILE;


sub main {

   my @array1;
   opendir ( DIR, $path ) || die "Error in opening dir $path\n"; 
   while ( $filelist = readdir (DIR) ) {
       next if ( $filelist =~ s/\.//g);   #/
       push @array1, $filelist;         
   }
   closedir(DIR);

   my @array2;
   open( my $fh, "<", "$path/$list") or die "Failed to open file: $!\n";   
   while(<$fh>) { 
      push @array2, $_;                  
   } 
   close $fh;

   my @result;
   foreach my $array2 (@array2) {
       foreach my $array1 (@array1) {
           if ($array1 !~ /$array2/ ) {
               push @result, "$array1\n";
           }
       }
   }

   print OUTFILE "",@result;  

}

标签: arraysalgorithmperlcomparison

解决方案


有几种方法可以做到这一点,也取决于具体需要什么。

为每个数组使用辅助散列,以将存在性检查减少为查找

use warnings;
use strict;
use feature 'say';

sub diff_arys {
    my ($ra1, $ra2) = @_;

    my %in_a1 = map { $_ => 1 } @$ra1;
    my %in_a2 = map { $_ => 1 } @$ra2;

    my @not_in_one = grep { not exists $in_a1{$_} } @$ra2;
    my @not_in_two = grep { not exists $in_a2{$_} } @$ra1;

    return (@not_in_one ? \@not_in_one : undef), 
           (@not_in_two ? \@not_in_two : undef);
}

my @ary1 = 'a'..'e';         # a,b,c,d,e
my @ary2 = ('a'..'d', 'z');  # a,b,c,d, z
    
my ($not_in_one, $not_in_two) = diff_arys(\@ary1, \@ary2);

say "@$not_in_one"  if $not_in_one;
say "@$not_in_two"  if $not_in_two;

印刷

z
e

这会发现两种方式的差异,一个数组中的元素而不是另一个数组中的元素。如果您确实知道您只需要一个“方向”来识别第一个数组中而不是第二个数组中的事物(从问题看来),然后调整 sub 以便只获得所需的返回。然后代码更少,你可以只返回数组(所以,一个列表或空)

注意接口的选择:undef如果没有发现差异则返回,否则返回数组引用。

这种工作有很好的模块。一个相当全面的是List::Compare。还有Array::UtilsArray::Compare等等。然后还有更复杂的工具也可以用于此,例如Algorithm::Diff


推荐阅读