http://qs1969.pair.com?node_id=752936

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

Hi there. Thanks everyone for all your help so far today. I have noe more question if thats ok. At the moment, my perl scripts output is this:
>ca106a84b6c03260e9e38b730b137664/1-17_107-243 1283 0.000 # - 0.331 # W 0.370 # D >a1b9ed2221c16448ebe19883994fa2db/1-95_130-213 1026 0.000 # M 0.331 # K 0.370 # N >fdecbdbac2f7f88b0cb666b87a69753a/76-219 209 0.000 # M 0.331 # T 0.370 # E
But I want it to be like this.
0.000 # -MM 0.331 # WKT 0.370 # DNE
But I'm not sure how to organise the print statements. code so far is as follows.
#!/usr/local/bin/perl use strict; use English; use Data::Dumper; use UNIVERSAL qw(isa); use FileHandle; use Exception; my $names = shift; my $alignment = shift; my $scorecons = shift; #my $lineno = 0; if (!$names || ! -e $names) { die new Exception("couldnt open names file $names"); } if (!$alignment || ! -e $alignment) { die new Exception("couldnt open names file $alignment $!"); } if (!$scorecons || ! -e $scorecons) { die new Exception("couldnt open names file $scorecons"); } warn "# Reading alignment data"; my $alignData = getAlignData($alignment); warn "# Got alignment data: ".scalar (keys %$alignData); #warn "# Reading scorecons data"; #my $scoreData = getScoreData($scorecons); #warn "# Got scorecons data: ".scalar (keys %$scoreData); warn "# Reading scorecons data\n"; my $scoreData = getScoreData($scorecons); warn "# Got scorecons data ".scalar @$scoreData; my $fhnames = new FileHandle($names) or die "Couldn't create file handle for $names"; while(my $line = $fhnames->getline) { my @cols = split /\s+/, $line; my $header = $cols[0]; my $align = $alignData->{$header}; my $number = $align->{line}; print "$header $number\n"; foreach my $item(@$scoreData) { # split each line of array into fields my @fields = split(/\s+/, $item); my $scorecons = $fields[0]; my $alignment = $fields[2]; my $align = substr($alignment, $number, 1); print "$scorecons # $align\n"; } #print "\n"; } ################################################# sub getAlignData { my ($fIn) = @ARG; my $fh = new FileHandle($fIn) or die ""; my $count = 0; my $hData = {}; while (my $line = $fh->getline) { my @cols = split /\s+/, $line; # search only for lines with identifier my $field = $cols[0]; my $test = substr($field, 0, 1); if("$test" eq ">") { # $count++; my $hEntry = { 'identifier' => $cols[0], 'line' => $count, }; $count++; #print "$cols[0] $count\n"; my ($record) = sort ($hEntry->{identifier}); $hData->{$record} = $hEntry; } } return $hData; } #################################################### sub getScoreData { my ($fIn) = @ARG; open(FILE, "$fIn") || die "Unable to open file\n"; my @data = <FILE>; return (\@data); }
Any advice much appreciated.

Replies are listed 'Best First'.
Re: how to format print statements with data from array
by AnomalousMonk (Archbishop) on Mar 24, 2009 at 20:27 UTC
    Something like this may be useful:
    use warnings; use strict; my %data; while (<DATA>) { chomp; my ($n, $d) = split; push @{ $data{$n} }, $d; } print "$_ # ", @{$data{$_}}, "\n" for sort keys %data; __DATA__ 0.000 - 0.331 W 0.370 D 0.000 M 0.331 K 0.370 N 0.000 M 0.331 T 0.370 E
    Output:
    >perl pm752936_1.pl 0.000 # -MM 0.331 # WKT 0.370 # DNE
Re: how to format print statements with data from array
by hsinclai (Deacon) on Mar 24, 2009 at 20:00 UTC
    BTW have you investigated format? At a quick glance it seems you could use it to eliminate some of the string parsing.
Re: how to format print statements with data from array
by jethro (Monsignor) on Mar 24, 2009 at 20:06 UTC

    Your question was a bit short on the underlying data it operates on. But if I read your code right, all you need to do is exchange your loops. I.e. the outer loop with the names/aligndata stuff should be inner loop and the loop over @$scoreData should be outer loop.

    The problem is that you read from a file ($fhnames) in the aligndata loop. If it gets to be inner loop it shouldn't do that anymore. Hopefully the data in the file is not to big to be read into memory, otherwise you might have to compact it or store it into a database. But since you want to print it in one line it seems that should not be a problem.

    After you have exchanged the loops all you need to do is collect the single chars instead of printing them directly and print the summary directly after the end of the inner loop

Re: how to format print statements with data from array
by bichonfrise74 (Vicar) on Mar 25, 2009 at 00:27 UTC
    Try this...
    #!/usr/bin/perl use strict; my %hash; while( <DATA> ) { next if ( /^>/ ); $hash{$1} .= $2 if ( /(\d\.\d+)\s+#\s+(.*)/ ); } foreach my $i (sort keys %hash) { print "$i # $hash{$i} \n"; }