1

I am new to Perl. I need to find the unique, count and sum for the following data. I request your help.

08/2009   I-111   300
08/2009   I-112   400
08/2009   I-113   500
10/2009   I-200   1000
10/2009   I-300   500
11/2009   I-300   100
11/2009   I-100   400

So I need to find like this

08/2009 3 1200
10/2009 2 1500
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user1016594
  • 71
  • 1
  • 1
  • 2

4 Answers4

2

uniq from List::MoreUtils returns the unique elements of a list:

use List::MoreUtils 'uniq';
my @x = uniq 1, 1, 2, 2, 3, 5, 3, 4;    # (1,2,3,5,4)

A list expression in scalar context returns the number of elements.

my @array = (5,6,7,8);
my $a_count = @array;       # 4

my %hash = ('x' => 1, 'y' => 2);
my $h_count = keys %hash;   # 2

sum from List::Util adds the elements of a list.

use List::Util 'sum';
my @array = (1,2,3,4,5);
print sum @array;   # 15
Zaid
  • 36,680
  • 16
  • 86
  • 155
yko
  • 2,710
  • 13
  • 15
  • Since `Scalar::Util` is one of core modules, looks like other way is to tag your question `homework` at first :) – yko Oct 27 '11 at 19:07
  • 2
    To be clear, the modules are 'List::Util' (singular) and 'List::MoreUtils' (plural). The former was added to the Perl core in 5.7.3; the latter is **not** part of the core distribution. 'Scalar::Util' is yet another core module from 5.7.3 but handles things other than sums and finding unique elements. – JRFerguson Oct 27 '11 at 20:11
1

Not sure what you want exactly, but is this ok?

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dump qw(dump);

my %h;
while(<DATA>) {
    chomp;
    my @el = split;
    $h{$el[0]}{count}++;
    $h{$el[0]}{sum} += $el[2];
}
dump%h;

__DATA__
08/2009   I-111   300
08/2009   I-112   400
08/2009   I-113   500
10/2009   I-200   1000
10/2009   I-300   500
11/2009   I-300   100
11/2009   I-100   400

output:

(
  "08/2009",
  { count => 3, sum => 1200 },
  "11/2009",
  { count => 2, sum => 500 },
  "10/2009",
  { count => 2, sum => 1500 },
)
Toto
  • 89,455
  • 62
  • 89
  • 125
  • Hi Thanks for help. But my Perl compiler cannot locate Data::Dump. – user1016594 Oct 27 '11 at 18:53
  • `cpan Data::Dump`, but thats just for visualization, you can use `Data::Dumper` which is a core module, its use is like `use Data::Dumper; ... ; print Dumper(\%h);` – Joel Berger Oct 27 '11 at 20:24
0

Re: M42's answer, try:

use Data::Dumper;
print Dumper \%h;

Or you could just write:

while (my ($key, $values) = each %h) {
    print "$key $values->{count} $values->{sum}\n";
}
flesk
  • 7,439
  • 4
  • 24
  • 33
  • Or if you use awk, it's as simple as: `awk '{count[$1]++;sum[$1]++} END {for (value in count) {print value,sum[value],count[value]}}' data.txt` – flesk Oct 27 '11 at 20:17
0

Normally, I don't do Write my program for free type stuff, but since M42 already did most of it, here's it is without the Data::Dump:

#!/usr/bin/perl
use strict;
use warnings;

my %h;
while(<DATA>) {
    chomp;
    my @el = split;
    $h{$el[0]}->{count}++;
    $h{$el[0]}->{sum} += $el[2];
}

foreach my $element (sort keys %h) {
    printf "%-10.10s  %-6.6s  %4d\n", $element, 
    $h{$element}->{count}, $h{$element}->{sum};
}
__DATA__
08/2009   I-111   300
08/2009   I-112   400
08/2009   I-113   500
10/2009   I-200   1000
10/2009   I-300   500
11/2009   I-300   100
11/2009   I-100   400   

Now learn yourself some Perl!

Community
  • 1
  • 1
David W.
  • 105,218
  • 39
  • 216
  • 337
  • Hi Thaks all for your response. When I am working I am getting my output as follows which is bizaare! I am using Solaris unix. When I run the code on Ubunu it gave me correct values: Could u explian me or correct me please? My output is 1/2009 ==========> 38821 01/2010 ==========> 32888 1/2209 ===>3 01/2011 ==========> 27134 which supposed to be – user1016594 Oct 31 '11 at 13:41
  • @user1016594 What version of Perl is on your Ubuntu box and on Solaris. My code should work with almost any version of Perl after 5.x. I'm not using anything that wasn't first introduced since version 5.x. To find the perl version run `perl -v`. – David W. Oct 31 '11 at 15:03