develooper Front page | perl.beginners | Postings from March 2011

RE: sub routine

Thread Previous | Thread Next
From:
Chris Stinemetz
Date:
March 17, 2011 21:03
Subject:
RE: sub routine
Message ID:
D225040F2D0F75448937B83D9527991A0154883003@denex1.cricketcommunications.com
>	>>>>> "CS" == Chris Stinemetz <cstinemetz@cricketcommunications.com> writes:

>	CS> Thanks Chris
>	CS> I am trying to build a sub routine that computes the following equation

>	CS> When $data[262] has the value of 1
>	CS> Take the value of $data[261] and return the solution of: $data[261]+13)/6.6/8/2*10)/10

>	CS> When I call the sub routine before I push the array I would like
>	CS> to return the value in 0.1 decimal.

>	that makes no sense. a floating number is just what it is. only when
>	printing it does counting decimal places make sense.

>	CS> use warnings;
>	CS> use strict;

>	CS> my $filepath = 'C:/temp/PCMD';
>	CS> my $outfile  = 'output.txt';

>	CS> open my $fh, '<', $filepath or die "ERROR opening $filepath: $!";
>	CS> open my $out, '>', $outfile or die "ERROR opening $outfile: $!";

>	CS> my @array = ();

>	CS> while (<$fh>){

>	better to assign the line to a variable. using $_ all the time isn't a
>	great idea for several reasons. the topmost one is that named variables
>	make the program more readable.

>	CS>                 next unless /;/;
>	CS>                 chomp;
>	CS>     my @data = split /;/;
>	CS>     my($cell,$sect,$chan,$carr,$dist,$precis) = ($data[31],$data[32],$data[38],$data[39],$data[261],$data[262]);

>	use a slice to save typing and eyestrain. you can access multiple
>	array/hash elements at one time:

>	my($cell,$sect,$chan,$carr,$dist,$precis) = @data[31,32,38,39,261,262];



>	CS>                                 if ($data[38] == 15)

>	why are you using @data again when you just assigned 38 to $chan? use
>	the scalar so it makes more sense to the reader.

>	rule: always write code so the reader will understand it.

>	CS>                                 {
>	CS>                                                 $data[39] = 2;
>	CS>                                 } else {
>	CS>                                                 $data[39] = 1;
>	CS>                                 }

>	again, use the scalar. and i don't see $data[39] used anywhere else so
>	that assignment is lost. also use the conditional expression. that whole
>	thing reduces to this:

>	$carr = ( $chan == 15 ) ? 2 : 1 ;

>	also since you are overwriting $chan there, you don't need it in the
>	slice above. $carr can be declared right here too.



>	CS>                                                 if( length($data[261]) > 12)
>	CS>                                                 {
>	CS>                                                                 $dist = getDist;
>	CS>                                                 }
>	CS>                                                 else
>	CS>                                                 {
>	CS>                                                                 $dist = "";
>	CS>                                                 }

>	ditto here.

>	my $dist = ( length( $dist ) > 1 ) ? getDist() : '' ;


>	CS>                 push @array, {

>	don't name arrays, @array. pick a name that describes the data in it.

>	CS>                                 cell => $cell,
>	CS>                                 sect => $sect,
>	CS>                                 carr => $carr,
>	CS>                                 RTD  => $RTD,

>	where does $RTD come from? i don't see it anywhere else so it will fail
>	under strict.

>	CS>                 };
>	CS> }

>	CS> my @sorted = map { $_->[0] }
>	CS>               sort {
>	CS>                  $a->[1] <=> $b->[1]
>	CS>                  || $a->[2] <=> $b->[2]
>	CS>                  || $a->[3] <=> $b->[3]
>	CS>               }
>	CS>               map { [ $_, $_->{cell}, $_->{sect}, $_->{carr} ]}
>	CS>               @array;

>	gack. i won't even address that now. but look at Sort::Maker on cpan for
>	an easier and more descriptive way to sort complex things.

>	also since you already have the values in a hash, there is no reason to
>	assign them to an array in there. 


>	CS> for my $tuple ( @sorted ){
>	CS>     print "$tuple->{cell} $tuple->{sect} $tuple->{carr} $tuple->{RTD}\n";
>	CS>                 }

>	slice to the rescue again:

>	print join( ' ', @tuple{ qw( cell sect carr RTD ), "\n" ;


>	CS> for my $tuple ( @sorted ){
>	CS>     print $out "$tuple->{cell} $tuple->{sect} $tuple->{carr} $tuple->{RTD}\n";
>	CS>                 }
>	CS>                 close $out;

>	but why print the same thing twice? store the string in a var, and then
>	print to both places. or even better, use File::Slurp and simplify.

>	here is a complete rewrite (untested):


>	use warnings;
>	use strict;

>	use File::Slurp ;

>	my $filepath = 'C:/temp/PCMD';
>	my $outfile  = 'output.txt';

>	my %cols = (

>	cell  => 31,
>	sect  => 32,
>	chan  => 38,
>	dist  => 261,
>	precis      => 262,
>	) ;

>	my @records ;

>	my @lines = read_file( $filepath ) ;

>	chomp @lines ;

>	foreach my $line ( @lines ) {

>	next unless $line =~ /;/ ;

>	my %record ;

>	# this gets just what you want into a hash using a hash slice and an
>	# array slice. the order of keys and values will be the same for any
>	# given hash

>	@record{ keys %cols } = (split /;/, $line)[ values %cols ] ;

>	$record{carr} = ( $record{chan} == 15 ) ? 2 : 1 ;     
>	$record{dist} = ( length( $record{dist}) > 1 ) ? getDist() : '' ;

>	push( @records, $record ) ;
>	}

>	my @sorted = sort {
>	$a->{cell} <=> $b->{cell} ||
>	$a->{sect} <=> $b->{sect} ||
>	$a->{carr} <=> $b->{carr}
>	} @records ;


>	my @report = map "@{$_{ keys %cols }}\n", @records ;

>	print @report ;
>	write_file( $output, @report ) ;


>	now isn't that a lot cleaner? some parts (all the slicing) may take a
>	little understanding but that isn't too hard.

>	uri

>	-- 
>	Uri Guttman  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
>	-----  Perl Code Review , Architecture, Development, Training, Support ------
>	---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------

Thanks for the explanations. This really cleaned up my code. Do you think you could explain to me how to get 
my dist sub routine to work correctly? I am very new to perl so please forgive my ignorance. 

I am getting the following errors.

syntax error at ./DOband1.pl line 12, near "$record{dist"
syntax error at ./DOband1.pl line 12, near "13)"
Execution of ./DOband1.pl aborted due to compilation errors.

My updated code is on the bottom.

#!/usr/bin/perl

use warnings;
use strict;

use File::Slurp;

my $filepath = 'C:/temp/PCMD';
my $output  = 'output.txt';

sub Dist {
      my $record{dist}+13)/6.6/8/2*10)/10 # I'm am not sure how to handle this. 
      }

my %cols = (
      cell  => 31,
      sect  => 32,
      chan  => 38,
      dist  => 261,
      precis      => 262,
);

my @records;

my @lines = read_file( $filepath );

chomp @lines;

foreach my $line ( @lines ) {

      next unless $line =~ /;/;

      my %record;

# this gets just what you want into a hash using a hash slice and an # array slice. 
# the order of keys and values will be the same for any # given hash

      @record{ keys %cols } = (split /;/, $line)[ values %cols ] ;

      $record{carr} = ( $record{chan} == 15 ) ? 2 : 1 ;     
      $record{dist} = ( length( $record{dist}) > 1 ) ? getDist() : '' ;

      push( @records, my $record ) ;
}

my @sorted = sort {
            $a->{cell} <=> $b->{cell} ||
            $a->{sect} <=> $b->{sect} ||
            $a->{carr} <=> $b->{carr}
      } @records ;


my @report = map "@{$_{ keys %cols }}\n", @records ;

print @report ;
write_file($output, @report) ;

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About