udinakar has asked for the wisdom of the Perl Monks concerning the following question:
Hi,
I have a array like this.
[[01 Jul 2007,221.6.19.196,9,19],
[01 Jul 2007,221.6.19.197,1,3],
[01 Jul 2007,221.6.19.196,12,12],
[01 Jul 2007,221.6.19.197,2 ,2],
[02 Jul 2007,202.119.104.22,1,1],
[02 Jul 2007,221.6.19.196,20,45],
[03 Jul 2007,202.119.104.12,1,11],
[03 Jul 2007,202.119.110.236,1,2],
[03 Jul 2007,210.29.132.9,1,2],
[03 Jul 2007,210.29.141.188,1,2],
[03 Jul 2007,221.6.19.195,3,7],
[03 Jul 2007,221.6.19.196,4,7],
[03 Jul 2007,222.192.2.213,1,0],
[03 Jul 2007,202.119.108.42,3,3]]
I need the output as
[[01 Jul 2007,221.6.19.196,21,31],
[01 Jul 2007,221.6.19.197,3,5],
[02 Jul 2007,202.119.104.22,1,1],
[02 Jul 2007,221.6.19.196,20,45],
[03 Jul 2007,202.119.104.12,1,11],
[03 Jul 2007,202.119.110.236,1,2],
[03 Jul 2007,210.29.132.9,1,2],
[03 Jul 2007,210.29.141.188,1,2],
[03 Jul 2007,221.6.19.195,3,7],
[03 Jul 2007,221.6.19.196,4,7],
[03 Jul 2007,222.192.2.213,1,0],
[03 Jul 2007,202.119.108.42,3,3]]
repeated ip count should be clubed for each day.
Please help
Thanks,
Dinakar
Re: Array question
by moritz (Cardinal) on Sep 05, 2007 at 10:47 UTC
|
Store the data in a hash, with Date+IP as the key and the repetition count as the value. When you enter an array item into the hash, you just add the count in the last column to the current value. | [reply] |
|
| [reply] [d/l] [select] |
Re: Array question
by andreas1234567 (Vicar) on Sep 05, 2007 at 10:48 UTC
|
use strict;
use warnings;
my %hash = ();
for (<DATA>) {
chomp;
my ($day, $ip, $i, $j) = split(q{,}, $_);
$hash{$day}{$ip}{i} += $i;
$hash{$day}{$ip}{j} += $j;
}
foreach my $day (sort keys %hash) {
foreach my $ip (sort keys %{$hash{$day}}) {
print qq{$day,$ip,} .
$hash{$day}{$ip}{i} . q{,}.
$hash{$day}{$ip}{j};
}
}
__DATA__
01 Jul 2007,221.6.19.196,9,19
01 Jul 2007,221.6.19.197,1,3
01 Jul 2007,221.6.19.196,12,12
01 Jul 2007,221.6.19.197,2 ,2
02 Jul 2007,202.119.104.22,1,1
02 Jul 2007,221.6.19.196,20,45
03 Jul 2007,202.119.104.12,1,11
03 Jul 2007,202.119.110.236,1,2
03 Jul 2007,210.29.132.9,1,2
03 Jul 2007,210.29.141.188,1,2
03 Jul 2007,221.6.19.195,3,7
03 Jul 2007,221.6.19.196,4,7
03 Jul 2007,222.192.2.213,1,0
03 Jul 2007,202.119.108.42,3,3
$ perl -l 637112.pl
01 Jul 2007,221.6.19.196,21,31
01 Jul 2007,221.6.19.197,3,5
02 Jul 2007,202.119.104.22,1,1
02 Jul 2007,221.6.19.196,20,45
03 Jul 2007,202.119.104.12,1,11
03 Jul 2007,202.119.108.42,3,3
03 Jul 2007,202.119.110.236,1,2
03 Jul 2007,210.29.132.9,1,2
03 Jul 2007,210.29.141.188,1,2
03 Jul 2007,221.6.19.195,3,7
03 Jul 2007,221.6.19.196,4,7
03 Jul 2007,222.192.2.213,1,0
Update: Renamed variables from $a, $b to $i, $j as adviced by GrandFather.
| [reply] [d/l] [select] |
|
| [reply] |
|
| [reply] |
|
Re: Array question
by GrandFather (Saint) on Sep 05, 2007 at 10:49 UTC
|
We like to see that you have made a little effort, partly so that we know you have actually thought about the problem and are not just hoping someone will save you having to do any work, and partly to gage your level of understanding of Perl and programming.
To get you started you should take a look at perlretut and perlre to gain a little understanding of pattern matching using regular expressions.
You will also find it helpful to go back to basics by looking at hashes and their application for managing data accessed by unique keys (see perldata).
DWIM is Perl's answer to Gödel
| [reply] |
|
Actually this is a table reterived from the database
and i tried this
my @new_duplicateip_results;
foreach my $first (@$select_result) {
foreach my $second (@$select_result) {
if ((@$first->[0] eq @$second->[0]) && (@$first->[1] eq @$seco
+nd->[1]) && (@$first->[$#{$first}] eq $self->product_id) && (@$second
+->[$#{$second}] eq "WS-".$self->product_id)) {
my $ip_string = "@$first->[0],@$first->[1],";
foreach (2..$#{$first}) {
$ip_string .= @$first->[$_]+@$second->[$_].",";
}
my @split_array = split(/,/,$ip_string) ;
push @new_duplicateip_results,\@split_array;
}
}
}
foreach (@new_duplicateip_results) {
print STDERR join "#",@$_;
print STDERR "\n";
}
However i need the values that are not matching the creiria.
If i include else then multiple rows are fetched.
Thanks,
Dinakar | [reply] [d/l] |
|
use strict;
use warnings;
use Data::Dump::Streamer;
my @data = (
['01 Jul 2007','221.6.19.196',9,19],
['01 Jul 2007','221.6.19.197',1,3],
['01 Jul 2007','221.6.19.196',12,12],
['01 Jul 2007','221.6.19.197',2,2],
['02 Jul 2007','202.119.104.22',1,1],
['02 Jul 2007','221.6.19.196',20,45],
['03 Jul 2007','202.119.104.12',1,11],
['03 Jul 2007','202.119.110.236',1,2],
['03 Jul 2007','210.29.132.9',1,2],
['03 Jul 2007','210.29.141.188',1,2],
['03 Jul 2007','221.6.19.195',3,7],
['03 Jul 2007','221.6.19.196',4,7],
['03 Jul 2007','222.192.2.213',1,0],
['03 Jul 2007','202.119.108.42',3,3],
);
my %sums;
$sums{$_->[0]}{a} += $_->[1], $sums{$_->[0]}{b} += $_->[2] for
map {["$_->[0],$_->[1]", @{$_}[2,3]]} @data;
my @result = map {[@{$_}[1, 2, 3, 4]]}
sort {$a->[0] cmp $b->[0]}
map {[$_, split (',', $_), @{$sums{$_}}{'a', 'b'}]} keys %sums;
Dump (\@result);
Prints:
$ARRAY1 = [
[
'01 Jul 2007',
'221.6.19.196',
21,
31
],
[
'01 Jul 2007',
'221.6.19.197',
3,
5
],
[
'02 Jul 2007',
'202.119.104.22',
( 1 ) x 2
],
[
'02 Jul 2007',
'221.6.19.196',
20,
45
],
[
'03 Jul 2007',
'202.119.104.12',
1,
11
],
[
'03 Jul 2007',
'202.119.108.42',
( 3 ) x 2
],
[
'03 Jul 2007',
'202.119.110.236',
1,
2
],
[
'03 Jul 2007',
'210.29.132.9',
1,
2
],
[
'03 Jul 2007',
'210.29.141.188',
1,
2
],
[
'03 Jul 2007',
'221.6.19.195',
3,
7
],
[
'03 Jul 2007',
'221.6.19.196',
4,
7
],
[
'03 Jul 2007',
'222.192.2.213',
1,
0
]
];
DWIM is Perl's answer to Gödel
| [reply] [d/l] [select] |
|
|
|
|
|
|
| [reply] [d/l] |
Re: Array question
by narainhere (Monk) on Sep 05, 2007 at 10:57 UTC
|
Build a hash with date and ip adress as key,and keep the values in an array
After reading the first two entries the hash would look like this,
%myhash{
"01 Jul 2007,221.6.19.196"=>[9,19],
"01 Jul 2007,221.6.19.197"=>[1,3]
}
Now the third ipaddress and date is same as first one,so add up the new values with the already existing values.Once you have parsed the entire list,can get you o/p by printing the key's and value's of the array.Please throw in some sentences on you next post's, your post looks like a command to a computer ;)
The world is so big for any individual to conquer
| [reply] [d/l] |
|
Sorry for being redundant.Didn't thought so many replies would have come before I post.
| [reply] |
Re: Array question
by Cristoforo (Curate) on Sep 05, 2007 at 23:43 UTC
|
I thought I'd post this solution because it has the two different sorts needed.Chris
#!/usr/bin/perl
use strict;
use warnings;
use Socket; # program uses the inet_aton and inet_ntoa functions
my %month;
@month{ qw/ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/} = '01'..
+'12';
my %data;
while (<DATA>) {
my ($date, $ip, $count1, $count2) = split /,/;
$data{$date}{ inet_aton($ip) }{count1} += $count1;
$data{$date}{ inet_aton($ip) }{count2} += $count2;
}
for my $date (sort by_date keys %data) {
for my $ip (sort keys %{ $data{$date} }) {
my $c1 = $data{$date}{$ip}{count1};
my $c2 = $data{$date}{$ip}{count2};
print join(",", $date, inet_ntoa($ip), $c1, $c2), "\n";
}
}
sub by_date {
my ($d_a, $m_a, $y_a) = split ' ', $a;
my ($d_b, $m_b, $y_b) = split ' ', $b;
my $A = "$y_a$month{$m_a}$d_a";
my $B = "$y_b$month{$m_b}$d_b";
$A cmp $B;
}
__DATA__
01 Jul 2007,221.6.19.196,9,19
01 Jul 2007,221.6.19.197,1,3
01 Jul 2007,221.6.19.196,12,12
01 Jul 2007,221.6.19.197,2 ,2
02 Jul 2007,202.119.104.22,1,1
02 Jul 2007,221.6.19.196,20,45
03 Jul 2007,202.119.104.12,1,11
03 Jul 2007,202.119.110.236,1,2
03 Jul 2007,210.29.132.9,1,2
03 Jul 2007,210.29.141.188,1,2
03 Jul 2007,221.6.19.195,3,7
03 Jul 2007,221.6.19.196,4,7
03 Jul 2007,222.192.2.213,1,0
03 Jul 2007,202.119.108.42,3,3
03 Aug 2007,221.6.110.9,1,2
03 Aug 2007,221.6.110.9,10,10
***prints
C:\perlp>perl t7.pl
01 Jul 2007,221.6.19.196,21,31
01 Jul 2007,221.6.19.197,3,5
02 Jul 2007,202.119.104.22,1,1
02 Jul 2007,221.6.19.196,20,45
03 Jul 2007,202.119.104.12,1,11
03 Jul 2007,202.119.108.42,3,3
03 Jul 2007,202.119.110.236,1,2
03 Jul 2007,210.29.132.9,1,2
03 Jul 2007,210.29.141.188,1,2
03 Jul 2007,221.6.19.195,3,7
03 Jul 2007,221.6.19.196,4,7
03 Jul 2007,222.192.2.213,1,0
03 Aug 2007,221.6.110.9,11,12
| [reply] [d/l] |
|
Thanks to one and all.
My apology for delayed response. I have taken the logic of GrandFather and tweaked it to my requirment it WORKED.
I was caught up with that work.
Special thanks to GrandFather.
I cannot do it from the database as there is a constraint in the logic built.
Thanks,
Dinakar
| [reply] |
|
|