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

I have a loop like this:
foreach( @line) { my ( $N, $V) = split( /delim/, $_); my $hash{ $N} = $V; }
is there a one liner possible ???

Replies are listed 'Best First'.
(Ovid) Re: new hash values
by Ovid (Cardinal) on Dec 04, 2001 at 23:56 UTC
Re: new hash values
by Masem (Monsignor) on Dec 04, 2001 at 23:54 UTC
    my %hash = map { (split /delim/, $_ )[0,1] } @line;

    -----------------------------------------------------
    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
    "I can see my house from here!"
    It's not what you know, but knowing how to find it if you don't know that's important

Re: new hash values
by dws (Chancellor) on Dec 04, 2001 at 23:59 UTC
    Masem nailed this. But on a side note, unless you are very certain that the value string cannot contain whatever your delimiter is, you are best of using the longer form of split() as follows:   my ($N, $V) = split(/delim/ $_, 2); If you don't do this, you risk truncating any values that embed the delimeter. Hand-rolled CGI form processors frequently get this wrong, turning a value of "a=b" into "a".

Re: new hash values
by VSarkiss (Monsignor) on Dec 05, 2001 at 00:54 UTC

    Actually, every single one of the above answers fails to duplicate what your code actually does: cause a syntax error. ;-).

    You cannot my a hash element. If you leave the my off the hash assignment, then any of the above should work for you.

Re: new hash values
by George_Sherston (Vicar) on Dec 05, 2001 at 00:02 UTC
    AFAIK you have to do the two steps of (A) splitting on the delimiter (B) doing the hash assignment - so reducing it to a one liner, if possible, wd be a cosmetic exercise.

    update: err... ok, reviewing the other posts I realise that one can do it in one step - so I live and learn! Sorry to be misleading. Meantime, back with the rest of my original post:

    But n.b. that however you do it you need to declare your hash outside the loop because otherwise each assignment will be a new hash (and also you have to declar a hash as a hash, not during the assignment, so what you have doesn't even do what it's not meant to do).

    You cd shorten it down to
    my ($N, $V, %hash); for (@line) { ($N, $V) = split /delim/; $hash{$N} = $V; }


    § George Sherston
Re: new hash values
by paranoid (Initiate) on Dec 05, 2001 at 17:26 UTC
    Thanks to all who helped me out, nice one-liner indeed !
    Off course you noticed its use for cgi :)
    to dws: it should be save to asume that following ='s are url-encoded
    if so we would need a function call to eg. url_decode() for the value. Hmm, url_decode could take two args change the second and return both, like this:
    my %hash = map { url_decode(split /delim/, $_ , 2) } @line;
    other ideas ?
      other ideas ?

      Use CGI.pm (docs) to parse your parameters? It will save you time, effort, pain, sweat, and bugs. Check out Ovid's web programming course (particularly Lesson Two) for tips on how to get started.

      perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^+*`^ ve^#$&V"+@( NO CARRIER'