Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

match two elements from an array in a row

by cengineer (Pilgrim)
on Aug 16, 2007 at 21:33 UTC ( [id://633177]=perlquestion: print w/replies, xml ) Need Help??

cengineer has asked for the wisdom of the Perl Monks concerning the following question:

I'm looking to find a particular number in an array twice in a row. More specifically, I'm looking to match 81 or 82. Is there a better or more elegant approach than something like:
my @data = qw ( 01 b2 01 00 b6 81 81 01 b4 0a 01 01 01 01 00 01 00 00 +01 00 c7 82 82 01 b2 01 00 b8 ); for ( my $i = 0; $i < $#data; $i++ ) { if ( $data[$i] eq "81" ) { if ( $data[$i+1] eq "81" ) { print "match 81 starting at index $i\n"; } } elsif ( $data[$i] eq "82" ) { if ( $data[$i+1] eq "82" ) { print "match 82 starting at index $i\n"; } } }
Thanks in advance!

Replies are listed 'Best First'.
Re: match two elements from an array in a row
by dogz007 (Scribe) on Aug 16, 2007 at 22:25 UTC
    You could use List::Util and take advantage of reduce:

    use strict; use List::Util qw(reduce); my @data = qw ( 01 b2 01 00 b6 81 81 01 b4 0a 01 01 01 01 00 01 00 00 01 00 c7 82 82 01 b2 01 00 b8 ); my $index; reduce { if ($a eq $b && $a =~ m/81|82/) { print "match $a starting at index $index\n"} $index++; $b; } @data;

    Prints:

    match 81 starting at index 6 match 82 starting at index 22

    Update: If you would prefer to use a for loop, you should use the range operator as below. Much cleaner to read. I guess I got carried away with the reduce.

    for my $i (0 .. $#data) { if ( $data[$i] eq $data[$i+1] && $data[$i] =~ m/81|82/) { print "match $data[$i] starting at index $i\n"; } }

      Perhaps premature optimization, but I'd recommend switching your tests around so that you only look for matches of numbers you care about:-

      if ($data[$i] =~ m/^(?:81|82)$/ && $data[$i] eq $data[$i+1]) {

      (Note the addition of anchors in the regex so you don't accidentally match a pair of, say, 181s.)

      And if the number of numbers you're trying to matches is likely to grow or change often, it may be easier using a hash instead of a regex:-

      my %wanted = map { $_, 1 } qw( 81 82 ); # ... for my $i (0 .. ($#data - 1)) { if (exists $wanted{$data[$i]} && $data[$i] eq $data[$i+1]) {

          --k.


Re: match two elements from an array in a row
by graff (Chancellor) on Aug 17, 2007 at 03:02 UTC
    my @data = qw( 01 b2 01 00 b6 81 81 01 b4 0a 01 01 01 01 00 01 00 00 01 00 c7 82 82 01 b2 01 00 b8 ); for ( 1 .. $#data ) { if ( $data[$_] =~ /(8[12])/ and $data[$_] eq $data[$_-1] ) { print "Match $1 ending at index $_\n"; } }
    (update: rearranged my conditions as perl Kanji's premature optimization. :)
Re: match two elements from an array in a row
by shoness (Friar) on Aug 17, 2007 at 08:53 UTC
    Just for fun, I wanted to try this with the regexp engine...
    #!/usr/bin/perl use strict; use warnings; my @data = qw ( 01 b2 01 00 b6 81 81 01 b4 0a 01 01 01 01 00 01 00 00 01 00 c7 82 82 01 b2 01 00 b8 ); $_ = join(' ', @data); while ( /(8[[:xdigit:]])\s+\1/g ) { print "Duplicate $1 found at character " . pos() . "\n"; }
    Produces...
    bash$ superdoc.pl Duplicate 81 found at character 20 Duplicate 82 found at character 68
    Using...
    # while ( /([[:xdigit:]]{2})\s+\1/g ) {
    instead, will match any repeated hex digit...
    bash$ superdoc.pl Duplicate 81 found at position 20 Duplicate 01 found at position 35 Duplicate 01 found at position 41 Duplicate 00 found at position 53 Duplicate 82 found at position 68
    Cheers!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://633177]
Approved by BrowserUk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (5)
As of 2024-04-18 01:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found