Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Matching elements inside two array

by ameezys (Acolyte)
on Apr 10, 2019 at 04:41 UTC ( #1232379=perlquestion: print w/replies, xml ) Need Help??
ameezys has asked for the wisdom of the Perl Monks concerning the following question:

I have three arrays such as below. What I want to do is if the element inside the arrays match, then it will do something. How do I correct this code?
@input_array = N1 N2 N3 N6 N7 @input_A = N1 N3 N11 N11 N10 N16 @input_B = N3 N6 N2 N7 N16 N19
if (grep { @input_B eq $_ } @input_array) { if (grep { @input_A eq $_ } @input_array) { foreach my $inputKey (@input_array) { @{$primaryCC0{$inputKey}} = (1,1); # each key of the hash +has an array with 2 values } foreach my $key (sort keys %primaryCC0) # to display value CC0 + and CC1 { my ($CC0, $CC1) = @{$primaryCC0{$key}}; print "CC0[$key] = $CC0\n"; print "CC1[$key] = $CC1\n\n"; } } else {print "only 1 input is PI";} } else {print "this is a wire\n\n";}

Replies are listed 'Best First'.
Re: Matching elements inside two arrays
by Athanasius (Bishop) on Apr 10, 2019 at 06:33 UTC

    Hello ameezys, and a belated welcome to the Monastery!

    You are using grep incorrectly. The block is applied to each element of the array in turn, setting $_ to that element. So

    grep { @input_B eq $_ } @input_array

    is testing each element of @input_array against @input_B, which makes no sense. You need something along these lines:

    for my $inputKey (@input_array) { if (grep { $inputKey eq $_ } @input_A) ... }

    As Marshall says, your requirements are not clear. I’m guessing you want to add an element to the hash %primaryCC0 when, and only when, that element is common to all three input arrays. In which case, the any function in List::Util is more efficient than grep:

    use strict; use warnings; use List::Util qw( any ); my @input_array = qw( N1 N2 N3 N6 N7 ); my @input_A = qw( N1 N3 N11 N11 N10 N16 ); my @input_B = qw( N3 N6 N2 N7 N16 N19 ); my %primaryCC0; for my $inputKey (@input_array) { if (any { $_ eq $inputKey } @input_A) { if (any { $_ eq $inputKey } @input_B) { @{ $primaryCC0{$inputKey} } = (1, 1); } else { print "$inputKey: only 1 input is PI\n"; } } else { print "$inputKey: this is a wire\n"; } } for my $key (sort keys %primaryCC0) { my ($CC0, $CC1) = @{ $primaryCC0{$key} }; print "CC0[$key] = $CC0\n"; print "CC1[$key] = $CC1\n"; }

    Output:

    16:27 >perl 1992_SoPW.pl N1: only 1 input is PI N2: this is a wire N6: this is a wire N7: this is a wire CC0[N3] = 1 CC1[N3] = 1 16:27 >

    Note that although @{ $primaryCC0{$inputKey} } = (1, 1); works (because of Perl’s autovivification), I would prefer to use:

    $primaryCC0{$inputKey} = [1, 1];

    which makes the creation of an anonymous array explicit.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Matching elements inside two array
by Marshall (Abbot) on Apr 10, 2019 at 05:24 UTC
    There are multiple things wrong here.
    Your code should always start with:
    use warnings; use strict;
    In general, an if within an if is wrong. This idea should be expressed if (X AND Y). That eliminates an indentation level and makes the code more clear. I have no idea what you are trying to do here..
    if (grep { @input_B eq $_ } @input_array) { if (grep { @input_A eq $_ } @input_array) { foreach my $inputKey (@input_array)
    Update: You ask "I have three arrays such as below. What I want to do is if the element inside the arrays match, then it will do something."

    Please explain what a "match" between these 3 array's means? I could not deduce that algorithm from your post.

Re: Matching elements inside two array
by hdb (Monsignor) on Apr 10, 2019 at 08:01 UTC

    In cases like this I prefer to first classify each label by setting a flag in which array it is present. I do this by using bits (1 for @input_array, 2 for @input_A, 4 for @input_B). In the second step the labels are processed based on their flags.

    use strict; use warnings; my @input_array = qw( N1 N2 N3 N6 N7 ); my @input_A = qw( N1 N3 N11 N11 N10 N16 ); my @input_B = qw( N3 N6 N2 N7 N16 N19 ); my %flags; $flags{$_} |= 1 for @input_array; $flags{$_} |= 2 for @input_A; $flags{$_} |= 4 for @input_B; my %primaryCCO; for (keys %flags) { next unless $flags{$_} & 1; print "$_: only 1 input is PI\n" if $flags{$_} == 3; print "$_: this is a wire\n" if $flags{$_} == 5; if( $flags{$_} == 7 ) { $primaryCCO{$_} = [1,1]; print "$_: CCO = ( @{$primaryCCO{$_}} )\n"; } }

    Remark: I have implied the desired logic from Athanasius output rather than studying your code, so I hope I got it right...

      And a version based on a dispatch table (which is definitely overkill in a simple situation like this):

      use strict; use warnings; my @input_array = qw( N1 N2 N3 N6 N7 ); my @input_A = qw( N1 N3 N11 N11 N10 N16 ); my @input_B = qw( N3 N6 N2 N7 N16 N19 ); my %flags; $flags{$_} |= 1 for @input_array; $flags{$_} |= 2 for @input_A; $flags{$_} |= 4 for @input_B; my %primaryCCO; my %dispatch = ( 3 => sub { my $label = shift; print "$label: only 1 input is PI\n" + }, 5 => sub { my $label = shift; print "$label: this is a wire\n" }, 7 => sub { my $label = shift; $primaryCCO{$label} = [1,1]; print "$label: CCO = ( @{$primaryCCO{$label}} )\n"; }, ); exists $dispatch{ $flags{$_}} and $dispatch{ $flags{$_} }->($_) for ke +ys %flags;
Re: Matching elements inside two array
by hippo (Canon) on Apr 10, 2019 at 07:52 UTC
Re: Matching elements inside two array
by ameezys (Acolyte) on Apr 10, 2019 at 17:07 UTC
    Sorry I forgot to mention the algorithm is that if the data inside input_A and input_B matches input_array, then the matching data for both input A and input B will store the value of CC0 and CC1 which is 1,1.
      ... if the data inside input_A and input_B matches input_array ... [emphasis added]

      Unfortunately, you also forgot to mention exactly what "matches" means in the context of your OP. Can you please at least say which of the responses you have so far received come closest to what you want?


      Give a man a fish:  <%-{-{-{-<

        Matches meaning that the any of the data for input A and input B is listed in the input array. So the listed data is the data that I want to store value of CC0 and CC1.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1232379]
Approved by Athanasius
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (5)
As of 2019-04-20 10:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    I am most likely to install a new module from CPAN if:
















    Results (108 votes). Check out past polls.

    Notices?
    • (Sep 10, 2018 at 22:53 UTC) Welcome new users!