How can I compare arrays in Perl?

后端 未结 12 2030
隐瞒了意图╮
隐瞒了意图╮ 2020-12-06 18:54

I have two arrays, @a and @b. I want to do a compare among the elements of the two arrays.

my @a = qw\"abc def efg ghy klm ghn\";
m         


        
相关标签:
12条回答
  • 2020-12-06 19:17

    Brute force should do the trick for small a n:

    my $flag = 0;
    foreach my $i (@a) {
        foreach my $k (@b) {
            if ($i eq $k) {
                $flag = 1;
                last;
            }
        }
    }
    

    For a large n, use a hash table:

    my $flag   = 0;
    my %aa     = ();
       $aa{$_} = 1 foreach (@a);
    foreach my $i (@b) {
        if ($aa{$i}) {
            $flag = 1;
            last;
        }
    }
    

    Where a large n is |@a| + |@b| > ~1000 items

    0 讨论(0)
  • 2020-12-06 19:18

    IMHO, you should use List::MoreUtils::pairwise. However, if for some reason you cannot, then the following sub would return a 1 for every index where the value in the first array compares equal to the value in the second array. You can generalize this method as much as you want and pass your own comparator if you want to, but at that point, just installing List::MoreUtils would be a more productive use of your time.

    use strict; use warnings;
    
    my @a = qw(abc def ghi jkl);
    my @b = qw(abc dgh dlkfj jkl kjj lkm);
    my $map = which_ones_equal(\@a, \@b);
    
    print join(', ', @$map), "\n";
    
    sub which_ones_equal {
        my ($x, $y, $compare) = @_;
        my $last = $#$x > $#$y ? $#$x : $#$y;
        no warnings 'uninitialized';
        return [ map { 0 + ($x->[$_] eq $y->[$_]) } $[ .. $last ];
    }
    
    0 讨论(0)
  • 2020-12-06 19:22
    my @a = qw' abc def efg ghy klm ghn ';
    my @b = qw' def ghy jgk lom com klm ';
    
    my $flag;
    
    foreach  my $item(@a) {
      $flag = @b~~$item ? 0 : 1;
      last if !$flag;
    }
    

    Note that you will need Perl 5.10, or later, to use the smart match operator (~~) .

    0 讨论(0)
  • 2020-12-06 19:25

    This is one way:

    use warnings;
    use strict;
    my @a = split /,/, "abc,def,efg,ghy,klm,ghn";
    my @b = split /,/, "def,ghy,jgk,lom,com,klm";
    my $flag = 0;
    my %a;
    @a{@a} = (1) x @a;
    for (@b) {
        if ($a{$_}) {
            $flag = 1;
            last;
        }
    }
    print "$flag\n";
    
    0 讨论(0)
  • 2020-12-06 19:25

    If you would consider the arrays with different order to be different, you may use Array::Diff

    if (Array::Diff->diff(\@a, \@b)->count) {
       # not_same
    } else {
       # same
    }
    
    0 讨论(0)
  • 2020-12-06 19:27

    This question still could mean two things where it states "If any element matches then set a flag":

    1. Elements at the same position, i.e $a[2] eq $b[2]
    2. Values at any position, i.e. $a[3] eq $b[5]

    For case 1, you might do this:

    # iterate over all positions, and compare values at that position
    my @matches = grep { $a[$_] eq $b[$_] } 0 .. $#a;
    
    # set flag if there's any match at the same position 
    my $flag = 1 if @matches;
    

    For case 2, you might do that:

    # make a hash of @a and check if any @b are in there
    my %a = map { $_ => 1 } @a;
    my @matches = grep { $a{$_} } @b;
    
    # set flag if there's matches at any position 
    my $flag = 1 if @matches;
    

    Note that in the first case, @matches holds the indexes of where there are matching elements, and in the second case @matches holds the matching values in the order in which they appear in @b.

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