Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

text formatting in columns with hash?

by Anonymous Monk
on Jul 03, 2013 at 18:56 UTC ( [id://1042255]=perlquestion: print w/replies, xml ) Need Help??

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

I have a text file in the form:
a b c 0 0 d 0 1 d 0 1 d 0 2 d 0 2 d 1 0 d 1 0 d 1 1 d 1 1 d 1 2 d 1 2 d
And want to get it into this form:
a b c a b c 0 0 d 1 0 d 0 1 d 1 0 d 0 1 d 1 1 d 0 2 d 1 2 d 0 2 d 1 2 d
I thought it would be easy to just load it into a hash and then be able to reprint it to a different file but it is not working since I can't figure out how to start back up at the top of a new column. This is what I have printing into one column:
foreach my $va (sort {$a <=> $b} keys %myhash) { foreach my $vb (sort {$a <=> $b} keys %{ $myhash{$va} }) { my $vc = $myhash{$va}{$vb}; print OUTFILE "$va\t$vb\t$vc\n"; } } }
I would appreciate any ideas for doing this effectivly.

Replies are listed 'Best First'.
Re: text formatting in columns with hash?
by toolic (Bishop) on Jul 03, 2013 at 19:46 UTC
    This works if you have an even number of lines after the header, as your output does (your input has an odd number for some reason):
    use warnings; use strict; my @lines = <DATA>; chomp @lines; my $head = shift @lines; print "$head $head\n"; my $count = @lines / 2; for my $i (0 .. $count-1) { print "$lines[$i] $lines[$i+$count]\n"; } __DATA__ a b c 0 0 d 0 1 d 0 1 d 0 2 d 0 2 d 1 0 d 1 0 d 1 1 d 1 2 d 1 2 d
      The requirements seem a bit more complicated. In the output, only the 'a' value is different between the two columns. The string which does not fit that pattern is skipped.
      UPDATE: My description of the output is wrong! I cannot figure out t +he real requirement.
      Bill
Re: text formatting in columns with hash?
by Loops (Curate) on Jul 03, 2013 at 20:09 UTC

    I'm late to the party here, but thought i'd post what i was playing around with anyway...

    #!/usr/bin/perl -w use 5.012; # Read in the header my $hdr = <DATA>; chomp $hdr; my @lines; my $line = 0; my $column = -1; my $previous_a = ''; while (<DATA>) { chomp; my ($a,$b,$c) = split; if ($a ne $previous_a) { $lines[0][++$column] = $hdr; $line = 1; $previous_a = $a; } $lines[$line++][$column] = $_; } $,="\t"; say map {defined($_) ? $_ : ''} (@$_) for (@lines); __DATA__ a b c 0 0 d 0 1 d 0 1 d 0 2 d 0 2 d 1 0 d 1 0 d 1 1 d 1 1 d 1 2 d 1 2 d 2 0 d 2 0 d 1 0 d 1 0 d 1 1 d 1 1 d 1 2 d 1 2 d
    Produces:
    a b c a b c a b c a b c 0 0 d 1 0 d 2 0 d 1 0 d 0 1 d 1 0 d 2 0 d 1 0 d 0 1 d 1 1 d 1 1 d 0 2 d 1 1 d 1 1 d 0 2 d 1 2 d 1 2 d 1 2 d 1 2 d
      Thanks so much everyone for all your help! I don't know if the output is going to be even or odd I just know that when the first column changes I wanted to start a new set of columns. The above code looks really good.
Re: text formatting in columns with hash?
by poj (Abbot) on Jul 03, 2013 at 19:45 UTC

    Fill an array, use the value in col a as the column number and reset rows back to 0 when it changes

    #!perl use strict; my @matrix=(); my $row = 0; my $prev_a; while (<DATA>){ chomp; my ($col_a,undef) = split(' ',$_,2); $row = 0 if ($col_a != $prev_a); $matrix[$row][$col_a] = $_; $prev_a = $col_a; ++$row; } for my $ar_row (@matrix){ print join " ",@$ar_row,"\n" } __DATA__ 0 0 d 0 1 d 0 1 d 0 2 d 0 2 d 1 0 d 1 0 d 1 1 d 1 2 d 1 2 d
    poj
Re: text formatting in columns with hash?
by 2teez (Vicar) on Jul 03, 2013 at 19:57 UTC

    Hi,
    ..I thought it would be easy to just load it into a hash and then be able to reprint it to a different file but it is not working since I can't figure out how to start back up at the top of a new column...

    You could do this:

    use warnings; use strict; use Data::Dumper; my $title =<DATA>; my %hash; while(<DATA>){ chomp; my $val = substr $_,0,1; push @{$hash{$val}},$_; } print Dumper \%hash; __DATA__ a b c 0 0 d 0 1 d 0 1 d 0 2 d 0 2 d 1 0 d 1 0 d 1 1 d 1 1 d 1 2 d 1 2 d
    which produces this..
    $VAR1 = { '1' => [ '1 0 d ', '1 0 d ', '1 1 d ', '1 1 d ', '1 2 d ', '1 2 d ' ], '0' => [ '0 0 d ', '0 1 d ', '0 1 d ', '0 2 d ', '0 2 d ' ] };
    UPDATE...
    You now have the hash you wanted, and since you have the title, in variable "$title", you can use it anytime you want.
    Though the printing out you desire is left for OP... :)
    Hope this helps.

    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1042255]
Approved by Happy-the-monk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2024-04-24 18:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found