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

Help! I have just started to work on a project that requires simple functions, but I'm not very familiar with linux or any programming languages. Could someone give me some help with simple arithmetic functions? I need to average some data and I know what I need to do, but I don't know how. I need to add up the times in column 3 and divide by the number of lines. The data looks like this:

example:
1234-5678 12 .345678
1234-5678 90 .123456

The first column is user id and process id, the second is the keystroke number, and the third is time in seconds. Could someone help me out with this? Thanks.

Replies are listed 'Best First'.
Re: Basic arithmetic functions
by dimmesdale (Friar) on Aug 08, 2002 at 17:22 UTC
    Check out split, it can be real helpful at times.

    # real important! use strict; use warnings; # this is the file where the data is my $file = 'path_to_file'; # these are some useful variables my $sum = 0; my $lines = 0; my $avgerage; # open file open(FH, $file) or die "File $file failed to open:"; #read file in line by line while(<FH>) { # get the third column and add it to $sum $sum += (split /\s+/, $_)[2]; # update $lines $lines++; } # now, to get the average, all you do is say $average = $sum/$lines;
Re: Basic arithmetic functions
by aufrank (Pilgrim) on Aug 08, 2002 at 17:30 UTC

    you could try something like:

    #! /opt/local/bin/perl -w # I recommend the strict pragma if you are new to perl use strict; # you could get the data you provided into an array in any # number of ways. my @data = ("1234-5678 12 .345678", "1234-5678 90 .123456"); my $sum; foreach (@data) { # puts each piece of information into its own variable # in case you need to use them for something. # you could push them into arrays to keep track of them my ($user_id, $proc_id, $time) = split(); # adds the time from the current line to the running # total of time values $sum += $time; } # divides the total times by the total number of times # (the index of the last element in the array + 1) my $average = $sum/($#data + 1); print $average;

    that is probably much longer than it needs to be, but it worked when I tested it on your data.

    good luck!
    --au

    update: bah! not only did Dimmesdale beat me to it, he had comments too! added comments.

Re: Basic arithmetic functions
by Hero Zzyzzx (Curate) on Aug 08, 2002 at 17:33 UTC

    Smells like homework.. . .

    -Any sufficiently advanced technology is
    indistinguishable from doubletalk.

Re: Basic arithmetic functions
by waswas-fng (Curate) on Aug 08, 2002 at 19:51 UTC
    You don't really say it, but it sounds like you may want to do the avg based on ID, so what I would do would be:
    my %procid; my %procidcount; open (FILE, "file"); while (<FILE>) { my ($id, $keystroke, $seconds) = split / /; $procid{"$id"} += $seconds; ($procidcount{"$id"})++ } foreach my $ids (sort keys %procid) { printf "Average for $ids is %f...\n", $procid{"$ids"} / $proci +dcount{"$ids"}; }
    where data in file looks like this:
    1234-5678 12 .345678 1234-5678 90 .123456 1234-5674 12 .345678 1234-5674 90 .123456 1234-5674 12 .345678
    and output looks like:
    Average for 1234-5674 is 0.271604... Average for 1234-5678 is 0.234567...

    -Waswas
Re: Basic arithmetic functions
by danboo (Beadle) on Aug 08, 2002 at 17:36 UTC
    hmm, for something like this i'd use:
    awk '{s += $3} END { print s/NR }' data.txt
    - danboo
      Anything awk can do...

      perl -lane '$s+=$F[2]}{print $s/$.'

      -sauoq
      "My two cents aren't worth a dime.";
      
        okay, i'll bite. why does this work?

        I mean, using an explicit END block i understand...

        perl -lane '$s+=$F[2]; END{print $s/$.;}'

        But what is it about your "}{" that makes the print part of an implicit END block? Is this documented behavior? or an unintenional artifact of the way the parser deals with -n ?