In Perl, is there a built in way to compare two arrays for equality?

后端 未结 13 2311
无人及你
无人及你 2020-11-27 17:08

I have two arrays of strings that I would like to compare for equality:

my @array1 = (\"part1\", \"part2\", \"part3\", \"part4\");
my @array2 = (\"part1\", \         


        
相关标签:
13条回答
  • 2020-11-27 17:16

    This question has turned into a very useful resource. ++ for the benchmarks and discussion.

    As others have pointed out smart match feature had issues and is being phased out in its current form. There are alternatives that are "less smart" (and so avoid the issues) and that are small, fairly fast and don't have too many non CORE dependencies.

    • Smart::Match
    • match::simple (and match::smart)
    • Scalar::In

    You can find links to some pretty good discussions about the history of the future of ~~ by looking at a couple of blog posts by @brian d foy, and the p5p mail archive threads from 2011 and 2012 from @rjbs.

    Comparing arrays can be simple and fun!

    use v5.20;   
    use match::smart; 
    my @x = (1, 2, 3);       
    my @y = qw(4 5 6);    
    my @z = qw(4 5 6);   
    say \@x |M| \@y ? "[\@x] and [\@y] match": "no match";  
    say \@y |M| \@z ? "[\@y] and [\@z] match": "no match";
    
    __END__                              
    @y and @z match, @x and @y do not
    

    ... especially fun if the array is simple. But an array can be a complicated thing, and sometimes you want different kinds of information from the results of the comparison. For that, Array::Compare can make fine tuned comparison easier.

    0 讨论(0)
  • 2020-11-27 17:18

    If order and duplicate values do not matter but only values equality (i.e. set comparison), you could use Set::Scalar.

    It overloads common operators such as == or !=.

    my @array1 = ("part1", "part2", "part3", "part4");
    my @array2 = ("part1", "PART2", "part3", "part4");
    
    if ( Set::Scalar->new(@array1) == Set::Scalar->new(@array2) ) {...}
    

    Alternatively, there's also Algorithm::Diff and List::Compare.

    0 讨论(0)
  • 2020-11-27 17:18

    If the only criteria is "are they equivalent or not?", and not the more complex question, "are they equivalent or not, and if they differ, how?" there are much quicker/uglier ways to do it. For example, smash the entirety of each array into two scalars and compare those.

    For example

    my @array1 = ("part1", "part2", "part3", "part4");
    my @array2 = ("part1", "PART2", "part3", "part4");
    
    my $smash1 = join("", @array1);
    my $smash2 = join("", @array2);
    
    if ($smash1 eq $smash2)
    {
      # equal
    }
    else
    {
      #unequal
    }
    

    Yes, I probably just made Larry Wall cry.

    0 讨论(0)
  • 2020-11-27 17:19

    So long as you are using perl 5.10 or newer, you can use the smart match operator.

    if (@array1 ~~ @array2) {...}
    
    0 讨论(0)
  • 2020-11-27 17:19

    Data::Cmp is another recent option. The cmp_data() function operates similarly to the cmp operator (see perlop for cmp usage).

    Example:

    use 5.10;
    use Data::Cmp qw/cmp_data/;
    
    my @array1 = ("part1", "part2", "part3", "part4");
    my @array2 = ("part1", "PART2", "part3", "part4");
    my @array3 = ("part1", "PART2", "part3", "part4");
    
    # sample usage 
    say "1 & 2 are different" if cmp_data(\@array1, \@array2) ;
    sat "2 & 3 are the same" unless cmp_data(\@array2, \@array3) ;
    

    It's also possible to compare hashes and more complicated nested data structures (within reason). For a single module with no non-core dependencies, Data::Cmp is pretty "smart" ;-) ... errm I mean "useful".

    0 讨论(0)
  • 2020-11-27 17:19

    One could use grep function in scalar context (http://perldoc.perl.org/functions/grep.html#grep-BLOCK-LIST)

    (0 eq (grep { $array1[ $_ ] ne $array2[ $_ ] } 0..$#array1)) if $#array1 eq $#array2;

    HIH.

    0 讨论(0)
提交回复
热议问题