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

Dear monks, I have a script which basically extracts information from an input file and prints it to various arrays. However, i want to be able to print the arrays so they form a tab-delimited matrix with each array being a column. Can anyone help?
# this is an example of how i create the arrays + for (my $i=0; $i < @dna; $i++) { ++$genome_size; + + # calculate the frequency of each dinucleo seperate to begin with # these are all symmetrised frequencies e.g Faa* + my $token = $dna[$i] . $dna[$i+1]; + if ($token =~ 'tt') { ++$tt_count; push @found, $i+1; $tt_pos = $i+1; # print "tt \t $tt_count \t $tt_pos\n"; push @tt_found, "$tt_count \t $tt_pos\n"; } + + if ($token =~ 'cg') { ++$cg_count; $cg_pos = $i+1; push @cg_found, "$cg_count \t $cg_pos\n"; } } print "@tt_found \t @cg_found\n";

Replies are listed 'Best First'.
Re: printing arrays
by Limbic~Region (Chancellor) on May 06, 2004 at 15:26 UTC
    Anonymous Monk,
    The question is what do you do if your arrays are not of equal length? I suggest using one of the MapCar() from Algorithm::Loops.
    #!/usr/bin/perl use strict; use warnings; use Algorithm::Loops 'MapCar'; my @array1 = 'a' .. 'm'; my @array2 = 1 .. 10; my @array3 = qw(john jacob jingle heimer smitz); MapCar(\&print_arrays, \@array1, \@array2, \@array3); sub print_arrays { print join "\t" , @_; print "\n"; }
    You will want to read the friendly manual to see which function is right for you - this is just an example.

    Cheers - L~R

Re: printing arrays
by davido (Cardinal) on May 06, 2004 at 16:06 UTC
    I wanted to present one more solution that doesn't require array padding.

    my @left = ( 1, 2, 3, 4, 5 ); my @mid = qw/ A B C D E /; my @right = qw/ A3 F7 3B 35 EF /; my $high = 0; $high = ( $high > $_ ) ? $high : $_ foreach $#left, $#mid, $#right; foreach my $idx ( 0 .. $high ) { local $, = "\t"; print map { ( exists $_->[$idx] ) ? $_->[$idx] : '' } \@left, \@mid, \@right; }

    This has the advantage of not adding useless padding to the end of your arrays. Plus it preserves the array, so you don't have to make a copy of it ahead of time.

    Once again it's untested: buyer beware.


    Dave

Re: printing arrays
by davido (Cardinal) on May 06, 2004 at 15:29 UTC
    Here's one simple method...

    my @left = ( 1, 2, 3, 4, 5 ); my @mid = qw/ A B C D E /; my @right = qw/ F1 E4 2C 77 1A /; print "$left[$_]\t$mid[$_]\t$right[$_]\n" for 0..$#left;

    You'll have to be sure that each of your arrays has the same number of elements; pad the ones that don't.


    Dave

      Hi dave, thanks for your solution, but how can I 'pad' out the shorter arrays? AM
        That's something you'll have to decide. Do you want them padded at the end, or at the beginning? Do you want them padded with empty strings, or zeros? The one thing you shouldn't do is leave them different lengths.

        Here's a subroutine you can use to "end pad" arrays with whatever string you prefer... as many arrays as you want.

        sub padarrays { my $padchar = shift; my @arrays = @_; my $max = 0; foreach my $aref ( @arrays ) { $max = ( @{$aref} > $max ) ? @{$aref} : $max; } foreach my $aref ( @arrays ) { my $padqty = $max - @{$aref}; next unless $padqty; push @{$aref}, $padchar x $padqty; } }

        The sub takes as its first argument a string (it can be empty, a number, or characters) that should be used to pad each array. It takes a list of array refs as the remainder of its parameters. It will then check the length of each array finding the longest, and pad all the rest of the arrays with your pad character so that they're all the same length.

        I didn't have time to test it, you may have to tweak a little to get it to work right. caviet emptor.


        Dave

Re: printing arrays
by idsfa (Vicar) on May 06, 2004 at 15:25 UTC

    Something like:

    @foo = (1,2,3);@bar=(4,5,6,7); while (@foo || @bar) { print "$foo[0]\t$bar[0]\n"; shift @foo; shift @bar; }

    Updated: Note that this solution does not require padding or modules. If you need the original arrays preserved, make copies.


    If anyone needs me I'll be in the Angry Dome.