"Chris Stinemetz"  wrote in message news

Hello List,

I have input data such as far below:

I would like to read the data into an array and modify the 2nd index if the
0th and first indices are identical.
I would like the updated 2nd index to be an average of the 2nd index where
both occurences of 0th and 1st indices match.

So for example below:

The records that contain 24 1 I would like to average the second index 60
and 40

and print the new value like this:

... # print input data
24 1 50 65
24 1 50 65
... # print rest of input data




22 1 60 65
22 2 180 90
22 3 300 90
23 1 0 65
23 2 90 65
23 3 260 65
24 1 60 65
24 1 40 65
24 2 180 65
24 2 160 65
24 3 310 65
24 3 290 65
. . . . .

Hi Chris,

I hope my identical post through Google groups doesn't find its way here. It
never made the list, so I'm re-posting from my email program. (Or, perhaps I
didn't trim enough in that post.)

There are many Perl idioms here, so if you don't understand parts, just ask.

It might be helpful to uncomment 'print Dumper \%data;' to visualize the
data structure I created.

I made a sub called 'sum', but if you have perl version 5.8 or higher, you
could use the sum function from List::Util. It is part of the perl
distribution and doesn't require installing the module from CPAN.

I read from the DATA filehandle, but am not including the data here as it is
the same as you provided in your question.

Chris

The program:

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

$Data::Dumper::Sortkeys = 1;

my %data;

while (<DATA>) {
   my ($col0, $col1, @rest) = split; # @rest is columns 2 and 3
   push @{ $data{$col0, $col1} }, \@rest;
}

#print Dumper \%data;

for my $comp_key (sort composite keys %data) {
   my $aref = $data{$comp_key}; # array_reference

   my $avg  = sprintf "%.f", sum( map $_->[0], @$aref ) / @$aref;

   my ($col0, $col1) = split /$;/, $comp_key;

   for my $i (0 .. $#$aref) {
       print join(" ", $col0, $col1, $avg, $aref->[$i][1]), "\n";
   }
}

sub composite {
   my ($a_col0, $a_col1) = split /$;/, $a;
   my ($b_col0, $b_col1) = split /$;/, $b;
   $a_col0 <=> $b_col0 || $a_col1 <=> $b_col1;
}

sub sum {
   my $sum;
   $sum += $_ for @_;
   return $sum;
}

__DATA__
22 1 60 65
22 2 180 90
22 3 300 90
23 1 0 65
. . . .

--
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