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

I have defined a hash array (code below) with the data (the form elements being radius and length and number) coming from a form.
$number=$values{"number"}; for ($i=1 ;$i<=$number ; $i++) { %conductordata = ("conductor$i" => [$values{"radius$i"}, $valu +es{"length$i"}]) }
in effect this sets up a hash with objects (or that is what is intended anyway) eg conductor1 => [25, 32]

What i want to do is print the data for each conductor in the hash in the format:

format OUT = # Conductor @>>>>>>@>>>> radius,length .
However i need to do each conductor on a new line. How do i reference print this format given that there are multiple conductors (ie many radius, length pairs)

Edit 2001-03-15 by tye

Replies are listed 'Best First'.
Re (tilly) 1: Printing Hash of Arrays
by tilly (Archbishop) on Mar 15, 2001 at 15:32 UTC
    There are better ways to clean this up (as already pointed out) but generally it is a good idea to avoid explicit C style loops. For instance instead of:
    for ($i=1 ;$i<=$number ; $i++) { ... }
    you can write:
    foreach $i (1..$count) { ... }
    which executes faster, and tends to result in less chance of fencepost errors. And of course I would never write a loop like that, I would instead do:
    foreach my $i (1..$count) { ... }
    which plays better with strict. (Which it doesn't look like you are using, but is a very helpful habit to get into.)
Re: Printing Hash of Arrays
by jeroenes (Priest) on Mar 15, 2001 at 13:24 UTC
    Just iterate over the keys of your data-hash, and derefence the array.
    for (keys %conductordata){ print OUT @{$conductordata{$_}}; }
    Or with some explicit dereferencing:
    for (keys %conductordata){ my $ref = $conductordata{$_}; print OUT $ref->[0..1]; }
    Which only returns the first and second item, to be safe.

    Hope this helps,

    Jeroen
    "We are not alone"(FZ)

    You can read more about it in perlref.

    Apparently not what Gremlin wanted to know. Gremlin, what exactly is yer problem? Just the thing busunsl pointed out, probably....

    I was asked for some deeper explanation for the hash overwrite. Well, It goes a bit deep. You'd probably want to read perldata on it. Perl differentiates between scalars, lists and hashes. So once you told the compiler a certain name (GLOB) represents a hash, it stays a hash. It even can coexist with a scalar by the same name!! (very confusing at first, but handy. It means you can say 'print $data for my $data (@data);'.)

    Having said this, a call to %some_hash always represents the whole hash. If you want an element, use $some_hash{element}. In your code, you assign to the whole hash in %conductordata = ("conductor$i"=>....... This results in a complete fresh hash, with only one element, but that in each iteration of your loop!

    All you have to do, is to assign to an one element each time. You only have the get the element before the '=': $conductordata{"conductor$i"} = [@elements].

    Moreover, your data fit conceptually into either a nested hash or a two-dimensional array:

    $number=$values{"number"}; my $con_data=[]; for ($i=1 ;$i<=$number ; $i++){ push @$con_data, [$values{"radius$i"}, $values{"length$i"}]; }
    Clean this up a little bit:
    my @numbers = grep{ s/radius(\d+)/$1/ } keys %values; $con_data[$i] = [$values{"radius$i"}, $values{"length$i"}] for my $i ( +@numbers); #then print: print OUT @$_ for (@$con_data);
Re: Printing Hash of Arrays
by busunsl (Vicar) on Mar 15, 2001 at 13:30 UTC
    With every loop you destroy the data in %conductordata, so perhaps you want to change it to:
    for ($i=1 ;$i<=$number ; $i++) { $conductordata{"conductor$i"} = [$values{"radius$i"}, $values{"length$i"}] }
    This way you get a hash element for each conductor. To print the data, you can do the following:
    for (keys %conductordata) { print "$conductordata[0] $conductordata[1]\n"; }
(boo)Re: Printing Hash of Arrays
by boo_radley (Parson) on Mar 15, 2001 at 22:39 UTC
    Here's a sample. The important thing is to decide what variable you're going to use to walk through %conductordata -- in the snippet below, I used $_ -- then use that in your format. Of course, I don't know what your data looks like, so I faked it. Also, please note that using a format doesn't matter if you're printing. The only thing that is affected by format is write.
    use strict; my $i; my %conductordata; format = # Conductor @>>>>>>>>>>@>>>>>>>>>> $conductordata{$_}{radius},$conductordata{$_}{length} . for ($i=1 ;$i<=10 ; $i++){ $conductordata{"conductor$i"}{radius}="radius$i"; $conductordata{"conductor$i"}{length}=$i**2; } foreach (sort keys %conductordata){write}
Re: Printing Hash of Arrays
by Gremlin (Acolyte) on Mar 15, 2001 at 13:19 UTC
    thats supposed to be print the format /ignore reference pls tanks