Hi Jim,

Thanks again. Very helpful as usual!

T.


On 2013-02-13, at 11:37 PM, Jim Gibson <jimsgib...@gmail.com> wrote:

> 
> On Feb 13, 2013, at 6:47 PM, Tiago Hori wrote:
> 
>> Hey Guys,
>> 
>> I am still at the same place. I am writing these little pieces of code to
>> try to learn the language better, so any advice would be useful. I am again
>> parsing through tab delimited files and now trying to find fish from on id
>> (in these case families AS5 and AS9), retrieve the weights and average
>> them. When I started I did it for one family and it worked (instead of the
>> @families I had a scalar $family set to AS5). But really it is more useful
>> to look at more than one family at time (I should mention that are 2 types
>> of fish per family one ends in PS , the other doesn't). So I tried to use a
>> foreach loop to go through the file twice, once with a the search value set
>> to AS5 and a second time to AS9. It works for AS5, but for some reason, the
>> foreach loop sets $test to AS9 the second time, but it doesn't go through
>> the while loop. What am I doing wrong?
>> 
>> here is the code:
>> 
>> #! /usr/bin/perl
>> use strict;
>> use warnings;
>> 
>> my $file = $ARGV[0];
>> my @family = ('AS5','AS9');
>> my $i;
>> my $ii;
>> my $test;
>> 
>> open (my $fh, "<", $file) or die ("Can't open $file: $!");
>> 
>> foreach (@family){
>>   $test = $_;
> 
> You can combine those two lines like this (for and foreach are equivalent, so 
> most people use the shorter form):
> 
>  for my $test ( @family ) {
> 
>>   my @data_weight_2N = ();
>>   my @data_weight_3N = ();
> 
> The second time through the for loop, the file has been read and is 
> positioned at its end. You are going to get nothing by reading the file the 
> second time through. You should rewind the file:
> 
>  seek($fh,0,0);
> 
>>   while (<$fh>){
>>       chomp;
>>       my $line = $_;
> 
> Once again, you can do the assignment directly and not use the default 
> variable $_. It is shorter and better:
> 
>  while( my $line = <$fh> ) {
>    chomp($line);
> 
>>       my @data  = split ("\t", $line);
>>       if ($data[0] !~ /[0-9]*/){
>>       next;}
> 
> Better syntax for those two lines:
> 
>  next if $data[0] !~ /[0-9]*/;
> 
>>       elsif ($data[1] eq "ABF09-$test"){
> 
> Then you can make the above line 'if …'
> 
>>           $i += 1;
>>           push (@data_weight_2N,  $data[6]);
>>       }elsif ($data[1] eq "ABF09-".$test."PS"){
>>       $ii += 1;
>>           push (@data_weight_3N,$data[6]);
>>   }
>> }
>>   my $mean_2N = &average (\@data_weight_2N);
>>   my $stdev_2N = &stdev (\@data_weight_2N);
> 
> You should not be calling subroutines with the ampersand character.
> 
>>   my $stderr_2N = ($stdev_2N/sqrt($i));
>> 
>>   print "These are the the avearge weight, stdev and stderr for $test
>> 2N:\t", $mean_2N,"\t",$stdev_2N,"\t",$stderr_2N, "\n";
> 
> It is more efficient to print one double-quoted string than a series of short 
> strings,
> even if you have to concatenate the string from two shorter strings:
> 
>   print "These are the the avearge weight, stdev and stderr for $test" .
>    " 2N:\t$mean_2N\t$stdev_2N\t$stderr_2N\n";
> 
>> 
>>   my $mean_3N = &average (\@data_weight_3N);
>>   my $stdev_3N = &stdev (\@data_weight_3N);
>>   my $stderr_3N = ($stdev_3N/sqrt($i));
>> 
>>   print "These are the the avearge weight, stdev and stderr for $test
>> 3N:\t", $mean_3N,"\t",$stdev_3N,"\t",$stderr_3N, "\n";
>> }
>> 
>> close ($fh);
>> 
>> sub average{
>>       my($data) = @_;
>>       if (not @$data) {
>>               print ("Empty array\n");
>>               return 0;
>>       }
>>       my $total = 0;
>>       foreach (@$data) {
>>               $total += $_;
>>       }
> 
> Shorter:
> 
>  $total += $_ for @$data;
> 
>>       my $average = $total / @$data;
>>       return $average;
>> }
>> 
>> sub stdev{
>>       my($data) = @_;
>>       if(@$data == 1){
>>               return 0;
>>       }
>>       my $average = &average($data);
>>       my $sqtotal = 0;
>>       foreach(@$data) {
>>               $sqtotal += ($average-$_) ** 2;
>>       }
>>       my $std = ($sqtotal / (@$data-1)) ** 0.5;
>>       return $std;
>> }
>> 
>> Thanks,
> 
> 
> --
> To unsubscribe, e-mail: beginners-unsubscr...@perl.org
> For additional commands, e-mail: beginners-h...@perl.org
> http://learn.perl.org/
> 
> 


--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to