For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > September 2007 > Pbm in Sorting the hash









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Pbm in Sorting the hash
Sivasakthi

2007-09-21, 7:00 pm

Hi all,

I have file like that following,

site_name access_time
www.google.com 14:13:04|14:13:04|
172.16.5.49 14:12:10|14:12:56|
172.16.65.53 14:12:41|14:12:58|
172.16.671.35 14:12:29|

from the above file i need to print the sites & no of accessed
connections with sort.


open(FILE,:/tmp/test.txt/" or die "cant open the file");

my @domain_info=<FILE>;
foreach my $site (@domain_info)
{
my ($domain,$data)=split(" ",$site);
$domain{$domain}.=$data;
}

foreach my $dname ( keys %domain)
{
my @conn=split('\|',$domain{$dname});
my $noofconn=$#conn+1;
$noofconns{$dname}+=$noofconn;

}
foreach $dname (sort {$noofconns{$b} <=> $noofconns{$a}} %noofconns)
{
print "$domain\n";
print "$noofconns\n";
}
close (<FILE> );

Could u help me to solve the pbm???

Thanks,
Siva


Tom Phoenix

2007-09-21, 7:00 pm

On 9/21/07, sivasakthi <msivasakthi@gmail.com> wrote:

> open(FILE,:/tmp/test.txt/" or die "cant open the file");


You probably meant a quote mark instead of a colon there.

> foreach $dname (sort {$noofconns{$b} <=> $noofconns{$a}} %noofconns)


It looks as if you want to use the keys() function there, just before
the name of the hash.

Hope this helps!

--Tom Phoenix
Stonehenge Perl Training
Rob Dixon

2007-09-21, 7:00 pm

sivasakthi wrote:
> Hi all,
>
> I have file like that following,
>
> site_name access_time
> www.google.com 14:13:04|14:13:04|
> 172.16.5.49 14:12:10|14:12:56|
> 172.16.65.53 14:12:41|14:12:58|
> 172.16.671.35 14:12:29|
>
> from the above file i need to print the sites & no of accessed
> connections with sort.
>
>
> open(FILE,:/tmp/test.txt/" or die "cant open the file");
>
> my @domain_info=<FILE>;
> foreach my $site (@domain_info)
> {
> my ($domain,$data)=split(" ",$site);
> $domain{$domain}.=$data;
> }
>
> foreach my $dname ( keys %domain)
> {
> my @conn=split('\|',$domain{$dname});
> my $noofconn=$#conn+1;
> $noofconns{$dname}+=$noofconn;
>
> }
> foreach $dname (sort {$noofconns{$b} <=> $noofconns{$a}} %noofconns)
> {
> print "$domain\n";
> print "$noofconns\n";
> }
> close (<FILE> );
>
> Could u help me to solve the pbm???



use strict;
use warnings;

my %noofconns;

open FILE, '/tmp/test.txt' or die "Can't open the file";

while (<FILE> ) {
my ($domain, $data) = split;
my $count = $data =~ tr/|//;
next unless $count;
$noofconns{$domain} += $count;
}
close FILE;

foreach my $domain (sort {$noofconns{$b} <=> $noofconns{$a}} keys %noofconns) {
print "$domain\n";
print "$noofconns{$domain}\n";
}

Rob
Chas. Owens

2007-09-21, 7:00 pm

On 9/21/07, sivasakthi <msivasakthi@gmail.com> wrote:
> Hi all,
>
> I have file like that following,
>
> site_name access_time
> www.google.com 14:13:04|14:13:04|
> 172.16.5.49 14:12:10|14:12:56|
> 172.16.65.53 14:12:41|14:12:58|
> 172.16.671.35 14:12:29|
>
> from the above file i need to print the sites & no of accessed
> connections with sort.
>


To start with, all Perl programs longer than one line should start with

#!/usr/bin/perl

use strict;
use warnings;

>
> open(FILE,:/tmp/test.txt/" or die "cant open the file");


Your use of parenthesis is defeating your use of "or die". This code
will only die if "/tmp/test.txt" is false (which it cannot be as it is
a non-empty string). You also have what I hope is a type there at the
start of the file string (: instead of "). Don't type code into
emails, always copy and paste. Try doing it like this instead

open my $file, '<', '/tmp/test.txt'
or die "could not open /tmp/test.txt: $!\n";

>
> my @domain_info=<FILE>;
> foreach my $site (@domain_info)


This is the worst way to read a file line by line. You are wasting
CPU time and memory. The right way is

while (my $site = <$file> ) {

> {
> my ($domain,$data)=split(" ",$site);
> $domain{$domain}.=$data;


The data structure you want here is not a hash of strings, but a hash
of arrays. Try

push @{$domain{$domain}}, $data;

or better yet

push @{$domain{$domain}}, split '|', $data;

> }
>
> foreach my $dname ( keys %domain)
> {
> my @conn=split('\|',$domain{$dname});
> my $noofconn=$#conn+1;
> $noofconns{$dname}+=$noofconn;
>
> }


This loop should be joined with the one above (see the second example)

> foreach $dname (sort {$noofconns{$b} <=> $noofconns{$a}} %noofconns)


sort takes a list not a hash, you need to say "sort {} keys %hash" instead.

> {
> print "$domain\n";
> print "$noofconns\n";


I think this is where your real problem is. $domain and $noofconns
hold nothing (they aren't even variables under strict). You should
have said

print "$dname had $noofconns{$dname} connections\n";

> }
> close (<FILE> );
>
> Could u help me to solve the pbm???
>
> Thanks,
> Siva
>
>


Here is how I would have solved the same requirements (if the sort is
too slow then it might be time to try a Schwartzian Transform on it):


#!/usr/bin/perl

use strict;
use warnings;

my %domain;

while (<DATA> ) {
my ($dom, $data) = split ' ';
push @{$domain{$dom}}, split /\|/, $data;
}

for my $dom (sort { @{$domain{$b}} <=> @{$domain{$a}} } keys %domain) {
print "$dom had " . @{$domain{$dom}} . " connections\n";
}

__DATA__
site_name access_time
www.google.com 14:13:04|14:13:04|
172.16.5.49 14:12:10|14:12:56|
172.16.65.53 14:12:41|14:12:58|
172.16.671.35 14:12:29|
John W. Krahn

2007-09-21, 9:59 pm

sivasakthi wrote:
> Hi all,


Hello,

> I have file like that following,
>
> site_name access_time
> www.google.com 14:13:04|14:13:04|
> 172.16.5.49 14:12:10|14:12:56|
> 172.16.65.53 14:12:41|14:12:58|
> 172.16.671.35 14:12:29|
>
> from the above file i need to print the sites & no of accessed
> connections with sort.
>
>
> open(FILE,:/tmp/test.txt/" or die "cant open the file");


You have a typo, :/tmp/test.txt/" should be "/tmp/test.txt". Also, you should
include the $! variable in the error message so you know *why* it failed.

open FILE, '<', '/tmp/test.txt' or die "cant open the file: $!";


> my @domain_info=<FILE>;
> foreach my $site (@domain_info)
> {
> my ($domain,$data)=split(" ",$site);
> $domain{$domain}.=$data;
> }
>
> foreach my $dname ( keys %domain)
> {
> my @conn=split('\|',$domain{$dname});
> my $noofconn=$#conn+1;
> $noofconns{$dname}+=$noofconn;
>
> }


There is really no good reason to read in the entire file at once:

my %noofconns;
while ( <FILE> ) {
my ( $domain, $data ) = split;
my @conn = split /\|/, $data;
$noofconns{ $domain } += @conn;
}
close FILE;


> foreach $dname (sort {$noofconns{$b} <=> $noofconns{$a}} %noofconns)


You forgot to use keys():

foreach my $dname ( sort {$noofconns{$b} <=> $noofconns{$a}} keys %noofconns )


> {
> print "$domain\n";
> print "$noofconns\n";


print "$dname $noofconns{$dname}\n";


> }
> close (<FILE> );



John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall
Dr.Ruud

2007-09-22, 7:00 pm

sivasakthi schreef:

> Could u help me to solve the pbm???



Try this first:

s/\bu\b/you/
s/\bpbm\b/problem/
s/\?{3}/?/

--
Affijn, Ruud

"Gewoon is een tijger."
Sivasakthi

2007-09-24, 4:00 am

On Fri, 2007-09-21 at 12:47 -0400, Chas. Owens wrote:

> On 9/21/07, sivasakthi <msivasakthi@gmail.com> wrote:
>




Thank you all for your response..


Thanks,
Siva

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com