Hello Perl Monks, I am practicing perl by picking up text parsing questions from StackOverflow and wrote the following script. The objective was to transpose the data from

Name^Code^Count Name1^0029^1 Name1^0038^1 Name1^0053^1 Name2^0013^3 Name2^0018^3 Name2^0023^5 Name2^0025^1 Name2^0029^1 Name2^0038^1 Name2^0053^1 Name3^0018^1 Name3^0060^1 Name4^0018^2 Name4^0025^5 Name5^0018^2 Name5^0025^1 Name5^0060^1
to this:
Name^0013^0018^0023^0025^0029^0038^0053^0060 Name1^^^^^1^1^1^ Name2^3^3^5^1^1^1^1^ Name3^^1^^^^^^1 Name4^^2^^5^^^^ Name5^^2^^1^^^^1
Here is my attempt on the answer:
use strict; use warnings; my $map; my $sep = '^'; my @flds; my %codes; # Loop through the lines and create hashmap while (my $line = <DATA>) { chomp $line; @flds = split ('\^', $line); next unless $.>1; $map->{$flds[0]}->{$flds[1]} = $flds[2] or next; $codes{$flds[1]}++; } # Print the header line print "Name"; foreach my $k (sort keys %codes){ print "$sep" . "$k"; } print "\n"; # Iterate through the hash foreach my $k1 (sort keys %$map) { print $k1; foreach my $k2 (sort keys %codes) { print "$sep" and next unless defined $map->{$k1}->{$k2}; print "$sep" . "$map->{$k1}->{$k2}"; } print "\n"; } __DATA__ Name^Code^Count Name1^0029^1 Name1^0038^1 Name1^0053^1 Name2^0013^3 Name2^0018^3 Name2^0023^5 Name2^0025^1 Name2^0029^1 Name2^0038^1 Name2^0053^1 Name3^0018^1 Name3^0060^1 Name4^0018^2 Name4^0025^5 Name5^0018^2 Name5^0025^1 Name5^0060^1

My first question is for these two lines of code:

print "$sep" and next unless defined $map->{$k1}->{$k2}; print "$sep" . "$map->{$k1}->{$k2}";

If I print the hash without the first statement, I get lot of warnings since I believe due to autovivification, perl tries to create the hash for missing key and grabs something not defined. How can I write this idiomatically. In awk I could do

printf "%s%s", FS, map[name[i],value[j]]

and it will print the value if key exists and will nothing if it doesn't. My second question is, do I really have to create

$codes{$flds[1]}++

Can I use the master map hash for iterating through just names? If so what would be the best way? Lastly, any tips of improving the script would be greatly appreciated. This is only my second post and from the first post I do see me making some progress thanks to everyone over here.


In reply to Print something when key does not exist by jaypal

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.