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

I would like to print data from 3 arrays: a(n), b(n,m) c(n,m)
where n and m can vary depending on the problem.
The data is simply column data for import with gnuplot.

a(0) b(0,0) c(0,0) b(0,1) c(0,1) b(0,2) c(0,2) ...
a(1) b(1,0) c(1,0) b(1,1) c(1,1)....
Here is a snippet of my attempt(s):

for my $i ( 0 .. $no_energy_bins ) { my $j=0; printf PLOUT "$energy_bin[$i] $spec_cps[$i][$j] $sigma_cps[$i][$j +]%s", $j<=$y_iter_max ? " " : "\n" while $spec_cps[$i][$j++]; # # for my $j ( 0 .. $max_y_locations ) { # printf PLOUT ( "%.5f %.5e %.5f %.5e %.5f %.5e %.5f %.5e %.5f \n", # $energy_bin[$i] $spec_cps[$i][$j] $sigma_cps[$i][$j]\t; ) # } # }

Both of these attempts can from similar questions on the site.
The first attempt is commented out.
How can you specify the format for "m" number of sequences (ie %.5e %.5f)?
Thanks, Bruce

Replies are listed 'Best First'.
Re: print arrays a(i), b(i,j) c(i,j)
by GrandFather (Saint) on Feb 13, 2006 at 04:26 UTC

    Your first attempt looked better but you need comas in there and you have too few parameters. For printing three values the following should work:

    printf PLOUT "%.5f %.5e %.5f\n", $energy_bin[$i], $spec_cps[$i][$j], $ +sigma_cps[$i][$j];

    However, that doesn't sound like it is what you really want. How about giving a complete snippet of code that runs and shows the problem you have. Something like this:

    use strict; use warnings; my @energy_bin = (1, 2, 3); my @spec_cps = ([5, 6], [7, 8], [9, 10]); my @sigma_cps = ([15, 16], [17, 18], [19, 110]); for my $j (0 .. $#energy_bin) { printf "%.5f %.5e %.5f %.5e %.5f\n", $energy_bin[$j], $spec_cps[$j][0], $sigma_cps[$j][0], $spec_cps[$j][1], $sigma_cps[$j][1]; }

    Prints:

    1.00000 5.00000e+000 15.00000 6.00000e+000 16.00000 2.00000 7.00000e+000 17.00000 8.00000e+000 18.00000 3.00000 9.00000e+000 19.00000 1.00000e+001 110.00000

    DWIM is Perl's answer to Gödel
      Thanks Grandfather, your code is close to what I want to do:
      for my $j (0 .. $#energy_bin) { printf "%.5f %.5e %.5f %.5e %.5f\n", $energy_bin[$j], $spec_cps[$j][0], $sigma_cps[$j][0], $spec_cps[$j][1], $sigma_cps[$j][1]; }
      How would I put a loop for the other array index( ie: 0, 1, 2,...,
      and also make the printf format entries flexible for
      different value of the array index ( ie 10 cols vice 4, etc)?

        The following probably gets close to what you want to do. Note $#{$spec_cps[$j]} is used to get the index of the last item in the array referenced by $spec_cps[$j]. See Re^2: print arrays a(i), b(i,j) c(i,j) if you don't understand what I mean by that.

        use strict; use warnings; my @energy_bin = (1, 2, 3); my @spec_cps = ([5, 6], [7, 8], [9, 10]); my @sigma_cps = ([15, 16], [17, 18], [19, 110]); for my $j (0 .. $#energy_bin) { printf "%.5f", $energy_bin[$j]; for my $i (0 .. $#{$spec_cps[$j]}) { printf " %.5e %.5f", $spec_cps[$j][$i], $sigma_cps[$j][$i]; } print "\n"; }

        Prints:

        1.00000 5.00000e+000 15.00000 6.00000e+000 16.00000 2.00000 7.00000e+000 17.00000 8.00000e+000 18.00000 3.00000 9.00000e+000 19.00000 1.00000e+001 110.00000

        DWIM is Perl's answer to Gödel
Re: print arrays a(i), b(i,j) c(i,j)
by ayrnieu (Beadle) on Feb 13, 2006 at 04:33 UTC
    use List::MoreUtils qw/zip/; sub emit_frobs { my ($a, $b, $c) = @_; for (@$a) { my @fb = map { sprintf "%.5f", $_ } @{shift @$b}; my @ec = map { sprintf "%.5e", $_ } @{shift @$c}; print PLOUT join(' ', $_, zip(@fb, @ec)), "\n"; } } emit_frobs \@energy_bins, \@spec_cps, \@sigma_cps;

    I don't understand the rest of your question, sorry.

Re: print arrays a(i), b(i,j) c(i,j)
by CountOrlok (Friar) on Feb 13, 2006 at 05:50 UTC
    To extend what GrandFather is saying above, Perl does not use the same type of syntax has C/C++ to refer to a multidimensional array. In C one would say spec_cps[i][j], while in Perl one would say $spec_cps[$i,$j]

    Look up the $; special variable to see what Perl is doing to mimic a true multidimensional array.

    -imran

      Hmm, not quite. In fact, not at all. $; controls the symbol used as a subscript seperator for multi-dimensional hashes, not arrays. Perl arrays are more like lists - they are dynamiclly sized and can not by managed in the same way that fixed size C arrays can be.

      To achieve multi-dimensional arrays in Perl you need to remember that a scalar can hold a reference to another object, for our purposes it can hold a reference to an array. So we implement multi-dimensional arrays by having an array of references to arrays.

      A little syntactic sugar makes accessing such multi-dimensional arrays identical with the equivelent C syntax. $AoA[0][0] accesses the first element in the first row of the array @AoA. @AoA is really an array of references to arrays. The syntactic sugar saves writing the access as $AoA[0]->[0]; to dereference the first element of @AoA then index into the array referenced by that element. Take a look at the two @xxxx_cps arrays in the code sample in Re: print arrays a(i), b(i,j) c(i,j) to see how they are initialised and how elements in them are accessed


      DWIM is Perl's answer to Gödel