Mark.Allan has asked for the wisdom of the Perl Monks concerning the following question:

firstly, all the best for the up and coming new year monks, secondly (script using strict and warnings as always :O) ) I have an hash of hashes with a pseudo structure as follows

$output{$mode}{category} $output{$mode}{division} $output{$mode}{priority} $output{$mode}{resolved} $output{$mode}{current} $output{$mode}{tis} $output{$mode}{customer} $output{$mode}{worker}

which can be printed out like below when each was just a single value but for keys "current" and "tis" I now have multiple values which I have joined up with a /n

for(sort keys %output) { print "$_,$output{$_}{category},$output{$_}{division},$output{$_}{ +priority},$output{$_}{resolved},$output{$_}{current},$output{$_}{tis} +,$output{$_}{customer},$output{$_}{worker}\n"; }

The list of which exists for say 'current' was populated with the following code <snippet>

while (m<CURRENT=(\S+)>gx) { $output{$mode}{current} = $1; push @{$cfg{$mode}{current}} => $output{$mode}{current +}; $output{$mode}{current} = join("\n",@{$cfg{$mode}{curr +ent}}); }

A dump of the hash now looks like this

$VAR1 = { 'AUTO' => { 'category' => 'Shelf', 'division' => 'deployment', 'priority' => '3', 'resolved' => 'YES', 'current' => 'CLOSED2/1 CLOSED2/2 CLOSED2/3 CLOSED2/4', 'tis' => '200 300 400 200', 'customer' => 'NO', 'worker' => 'YES', } };

How can I change my print statement so I can print as follows:

AUTO,Shelf,deployment,3,YES,CLOSED2/1,200,NO,YES AUTO,Shelf,deployment,3,YES,CLOSED2/2,300,NO,YES AUTO,Shelf,deployment,3,YES,CLOSED2/3,400,NO,YES AUTO,Shelf,deployment,3,YES,CLOSED2/4,200,NO,YES

Any help with this would be much appreciated

Replies are listed 'Best First'.
Re: Printing hash values
by tangent (Parson) on Dec 27, 2013 at 14:41 UTC
    Assuming the number of lines in 'current' is the same as in 'tis':
    my @pfx_keys = qw( category division priority resolved ); my @sfx_keys = qw( customer worker ); for my $key (sort keys %output) { my $val = $output{$key}; my @pfx = map { $val->{$_} } @pfx_keys; my @sfx = map { $val->{$_} } @sfx_keys; my @current = split("\n",$val->{'current'}); my @tis = split("\n",$val->{'tis'}); for my $i (0 .. $#current) { my $line = join(',',$key,@pfx,$current[$i],$tis[$i],@sfx); print "$line\n"; } }
    Output:
    AUTO,Shelf,deployment,3,YES,CLOSED2/1,200,NO,YES AUTO,Shelf,deployment,3,YES,CLOSED2/2,300,NO,YES AUTO,Shelf,deployment,3,YES,CLOSED2/3,400,NO,YES AUTO,Shelf,deployment,3,YES,CLOSED2/4,200,NO,YES

      This works perfectly, thank you

Re: Printing hash values
by VincentK (Beadle) on Dec 27, 2013 at 16:30 UTC
    Hi Mark.Allan

    As with tangent my solution assumes that 'current' and 'tis' contain the same number of items.

    I am not sure if my solution is any better ( six of one, half a dozen of the other), but you can change the order of the PRINT_ORDER array to easily change the order of the output. At the very least, I had fun with this one. :)

    Update: I removed a testing line I had in there for SUB_GROUP.

    use strict; use warnings; my %_COLLECTION_HOH = ( 'AUTO' => { 'category' => 'Shelf', 'division' => 'deployment', 'priority' => '3', 'resolved' => 'YES', 'current' => 'CLOSED2/1 CLOSED2/2 CLOSED2/3 CLOSED2/4', 'tis' => '200 300 400 200', 'customer' => 'NO', 'worker' => 'YES', }, ); my @PRINT_ORDER = qw(category division priority resolved current tis c +ustomer worker); for my $PARENT_GROUP ( keys %_COLLECTION_HOH ) { ## Split up items in the 'current' and 'tis' sets and remove extra + whitespace my @CURRENT_ITEMS = map{s/^\s+//;s/\s+$//;$_} split(/\n/, $_COLLE +CTION_HOH{$PARENT_GROUP}{'current'} ); my @TIS_ITEMS = map{s/^\s+//;s/\s+$//;$_} split(/\n/, $_COLLE +CTION_HOH{$PARENT_GROUP}{'tis'} ); ## Assumes that 'current' and 'tis' have an equal number of items for (my $CURRENT_ITEM_ITER = 0; $CURRENT_ITEM_ITER <= $#CURRENT_IT +EMS; $CURRENT_ITEM_ITER++) { my $value = undef; print "$PARENT_GROUP,"; for(0..$#PRINT_ORDER) { if ($PRINT_ORDER[$_] eq 'current') { $value .= "$CURRENT_ITEMS[$CURRENT_ITEM_ITER]," if + $_ <$#PRINT_ORDER; $value .= "$CURRENT_ITEMS[$CURRENT_ITEM_ITER]" if +$_ == $#PRINT_ORDER; } elsif ($PRINT_ORDER[$_] eq 'tis') { $value .= "$TIS_ITEMS[$CURRENT_ITEM_ITER]," if $_ +<$#PRINT_ORDER; $value .= "$TIS_ITEMS[$CURRENT_ITEM_ITER]" if $_ = += $#PRINT_ORDER; } else { $value .= "$_COLLECTION_HOH{$PARENT_GROUP}{$PRINT_ +ORDER[$_]}," if $_ <$#PRINT_ORDER; $value .= "$_COLLECTION_HOH{$PARENT_GROUP}{$PRINT_ +ORDER[$_]}" if $_ == $#PRINT_ORDER; } } print "$value\n"; } }
      Hmm, Vincent, I am afraid that the "nice reference site" link you provided is infringing copyright, intellectual property and other laws... In brief, I think it is stolen intellectual property. If it is confirmed that I am right, I am pretty sure you did not realize. If I am wrong, just forget it.

        Egg on my face...

        I certainly hope the link is on the up and up, as it was not my intent to pass along a questionable reference. I removed it just to be safe. Thanks.
Re: Printing hash values
by McA (Priest) on Dec 27, 2013 at 14:39 UTC

    Hi,

    why do you join values of key current and tis, when you have to iterate over them in your ouput routine?

    My proposal: Don't join them, but push them to an array ref beyond the key current and tis. In the output routine you have to iterate over them keeping the variables for the values (category, division, etc.) constant.

    Regards
    McA