Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re: Getting element of array with a match

by tachyon (Chancellor)
on Dec 23, 2002 at 14:42 UTC ( [id://221861]=note: print w/replies, xml ) Need Help??


in reply to Getting element of array with a match

While grep is handy it it not efficient as you always search the whole array even if you find a match in the first element. Assuming your '100X' are unique product ids this is probably the most efficient way (although by no means the only way) to do it (the last means we stop searching at the first match. If we find a match string will be defined. If there is not match it will be undef. If you have comma separated data split will work fine. Substring works on the assumption of fixed width records so if someone enters say '1010   ' you would end up getting ' ,string' back which is not what you want. The correct syntax to get all the stuff after 5 chars (4 digits and the comma) is $string = substr $line, 5;

Your grep is broken because when you say $scalar = grep... you get the number of matches not the actual array elements(s). If you call grep in array context @ary = grep... then you get an array of all the elements that matched - if there is only one it will be $ary[0]. Many functions in perl exhibit this schizophrenic behaviour - it is called scalar/array context.

my @ary = <DATA>; my $find_id = 1006; my ($code, $string ); for my $line( @ary ) { next unless $line =~ m/^$find_id/; chomp $line; ( $code, $string ) = split ',', $line; last; } if ( $string ) { print "Found '$string'\n"; } else { print "No match!\n"; } __DATA__ 1001,choochoo 1002,candycane 1003,sockpuppet 1004,choochoo 1005,candycane 1006,sockpuppet6 1007,foo 1008,bar

cheers

tachyon

s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Fixed errant [] chars dvergin 2002-12-23

Replies are listed 'Best First'.
Re: Re: Getting element of array with a match
by Arien (Pilgrim) on Dec 24, 2002 at 04:18 UTC

    The thing that bugs me most about that snippet is the match-chomp-split sequence. I prefer:

    my $id = 1006; my $answer; for (@data) { last if ($answer) = /^\Q$id\E\s*,(.*)/o; }

    — Arien

    Update: Added /o and allowed for optional whitespace between id and comma per tachyon's worries below.

      Sure, that's the sort of way I would usually code it myself but you then have to (potoentially) explain how that single line works. There is also an implicit requirement in your code that the comma imediately follows the id as well as having no leading whitespace. All probably true but... You should have either used qr// or /o in your code BTW ;-)

      For those that are wondering the \Q...\E is the regex version of quotemeta which ensures that interpolated strings do not blow up your regex when they contain metachars. It is always sound practice to use \$Q$string\E in regexes.

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

        (Also see update in my post above.)

        Sure, that's the sort of way I would usually code it myself but you then have to (potentially) explain how that single line works.

        The only thing that might have to be explained is that matching in a list context returns a list of the captured subexpressions.

        The fragment is idiomatic Perl, so somebody maintaining Perl code should at least be able to read it. I wouldn't think twice about writing it like this.

        — Arien

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (2)
As of 2024-04-24 23:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found