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

Monks,

I've got a nice one liner that loads a file of recs into a hash, each rec being of the format name:val, like so

%t_hash = map{ split(/:/, $_, 2) } <DATA_FILE>;
However, I've got another prog I want to use on the same data format, but the data is being fed in one rec at a time, so I need to accumulate the data, conceptually like this
%t_hash += map{ split(/:/, $_, 2) } $rec;
Obviously this doesn't work ("Can't modify private hash in addition (+) at ./t.pl line 250, near "$var1;" Execution of ./t.pl aborted due to compilation errors. ").

I've tried a few variations, but can't find the solution (which I'm sure must be possible).
Anybody got the answer?
Cheers
Chris
PS I'm just curious about a 1-liner, I know i could use 2 eg

($key, $val) = split(/:/, $rec, 2); $t_hash{$key} = $val;

Replies are listed 'Best First'.
Re: Accumulating data in a hash using map{split()}
by merlyn (Sage) on May 03, 2007 at 22:59 UTC
Re: Accumulating data in a hash using map{split()}
by GrandFather (Saint) on May 03, 2007 at 23:11 UTC
    use strict; use warnings; my $str = "name:val with a :"; my %hash; $hash{$_->[0]} = $_->[1] for [split /:/, $str, 2]; print map {"$_:$hash{$_}\n"} keys %hash;

    Prints:

    name:val with a :

    but I'd not recommend it for production work. The two line variant is a lot less magical.

    Note the third parameter to the split though.


    DWIM is Perl's answer to Gödel
Re: Accumulating data in a hash using map{split()}
by chrism01 (Friar) on May 03, 2007 at 23:36 UTC
    Guys,
    Thx for those.

    Re: Grandfather: actually I'm already using the 3rd param because some values can have ':' in them, but I agree your solution looks a bit obscure/magical.

    I think I'll go with merlyn, as it's basically just hash merging like %a = (%b, %c), except of course it's $rec instead of <DATA>, for anybody else who reads this thread.

    Thx again
    Chris

      Actually I'd consider Merlyn's variant even more magical, but an idiom well worth knowing.

      There is a tension here between "succinct" and "lucid" with the two line version being at the lucid end of the spectrum and either of the one line solutions being toward the succinct end.

      You may find:

      %hash = (%hash, split /:/, <DATA>, 2);

      a little less magical than the variant using map btw in a context where you are dealing with single lines.


      DWIM is Perl's answer to Gödel
      ... and btw, it's a small amt of data, so efficiency isn't an issue

      Chris