Gossamer Forum
Home : General : Perl Programming :

Perl sort question

Quote Reply
Perl sort question
Hello,
I have a small .txt database with 5 fields.
Now I want to sort for the 5. field and print that out.
The 5. field is a field with numbers in it (10, 35, 22, 100, ...).
The Database looks like this: field1|field2|field3|field4|number
I test the following:

# Get the settings from the data file.
if(-e $datafile) {
open (DATA, "<$datafile");
LINE: while(<DATA> ){
next LINE if (/^#/);
next LINE if (/^\s*$/);
@data=split (/\|/);
$feld5{$data[0]} = $data[4];
$feld1{$data[0]} = $data[0];
close(DATA);
}
}
else {
print "<p>No file found.\n";
exit;
}
my $count=1;
foreach $field (sort { $feld5{$b} <=> $feld5{$a} } keys %feld5) {
if ($count <= 4) {
$output .= "$count. - $feld1{$field} - $feld5{$field}
\n";
}
$count++;
}
print "Content-type: text/html\n\n";
print qq~$output~;


But only the first dataset (first line of the database) will be shown.
I must say to this I'm not a sort funktion professional.
Has anyone a hint for me to do that!?

Another question. What does exact this lines mean (I saw that in a script in GT Forum and try that to sort):

next LINE if (/^#/);
next LINE if (/^\s*$/);


My Perl books won't give me an answer on this 2 problems.
If is it stupid what I did, is it possible to do that in another way?

DelPierro
http://www.simball.de/links_mods/
Quote Reply
Re: Perl sort question In reply to
In Reply To:
next LINE if (/^#/);
next LINE if (/^\s*$/);
Skips commented and blank lines.

The ^ followed by # basically checks for # at the beginning of a line so...

# bla bla

....would be ignored.

For the second bit, ^ is the beginnig of the line again, and \s stands for a blank space then *$ checks for a space all the way to the end of the line - ie and empty line :)

In somes place you have $feld and others $field - looks like you haven't checked your code thoroughly.

To split the data you can use...

if (-e $datafile) {
open (DATA, "<$datafile");
@data=<DATA>;
close(DATA);
}

foreach $line (@data) {
chomp $line;
($field1,$field2,$field3,$field4,$number) = split(/\|/,$line);
print $number;
}

Then you have $number which contains the value of the number for each line so in the example above, every number will be printed due to print $number; inside the loop.





Paul Wilson.
http://www.wiredon.net/gt/
http://www.perlmad.com/
Quote Reply
Re: Perl sort question In reply to
Hello.

1.
next LINE if (/^#/);
next LINE if (/^\s*$/);
= Skips commented and blank lines. Thank's for your explanation.

2.
The second, I want to make it easier to understand.
The code again (that's my original code):
# Get the settings from the data file.
if(-e $datafile) {
open (DATA, "<$datafile");
LINE: while(<DATA> ){
next LINE if (/^#/);
next LINE if (/^\s*$/);
@data=split (/\|/);
$points{$data[0]} = $data[4];
$name{$data[0]} = $data[0];
close(DATA);
}
}
else {
print "<p>No file found.\n";
exit;
}
my $count=1;
foreach $field (sort { $points{$b} <=> $points{$a} } keys %points) {
if ($count <= 4) {
$output .= "$count. - $name{$field} - $points{$field}
\n";
}
$count++;
}
print "Content-type: text/html\n\n";
print qq~$points - $name~;


The database is sorted by (A-Z) $name (field 0). Now I want to sort the database by (0-9) $points (field 4) and print out the datasets sorted by $points. The lowest number at the beginning or the highest number at the beginnig - like a user ranking. E.g. for case 2 (highest number at the beginning):
Name Paul - 26 points
Name DelPierro - 22 points
Name ... - ... points


But the database looks like the following:
DelPierro|...|...|...|22
Paul|...|...|...|26
...|...|...|...|...


I hope that's clearer and somebody could give me a hint. Wink

3.
In Reply To:
To split the data you can use... ...the example above...
That's clear for me, but that does not sort.

DelPierro
http://www.simball.de/links_mods/
Quote Reply
Re: Perl sort question In reply to
Yes I know my example doesn't sort - I was just showing you how to split it.

In Reply To:
next LINE if (/^#/);
next LINE if (/^\s*$/); = Skips commented and blank lines. Thank's for your explanation.
No,

This skips comment lines (/^#/)

This skips blank lines (^\s*$/)


Using the code I gave can you not just use.....

foreach $line (sort { $number{$a} <=> $number{$b} })

Paul Wilson.
http://www.wiredon.net/gt/
http://www.perlmad.com/
Quote Reply
Re: Perl sort question In reply to
Sorry, I was thoughtless. Blush
I my posting above I wanted to write the following:
next LINE if (/^#/); and next LINE if (/^\s*$/); = Skips commented and blank lines. Thank's for your explanation. It's clear. Wink

DelPierro
http://www.simball.de/links_mods/
Quote Reply
Re: Perl sort question In reply to
In Reply To:
Using the code I gave can you not just use.....

foreach $line (sort { $number{$a} <=> $number{$b} })
No, because you never nested his data (ie, a hash of arrays like his original code had).

I'm using the following to read data from a database:
Code:
open (LOG, "hits.db");
while () {
chomp ($line = <LOG>);
!$line and last;
($id, $rec{title}, $rec{status}, $rec{hits}) = split /\|/, $line;
$data{$id} = { %rec };
}
close (LOG);
Then I use the following to sort by hits (largest to smallest) and extract the top 3:
Code:
sub pop {
$i=0;
foreach $rec (sort {$data{$b}{hits} <=> $data{$a}{hits}} keys (%data)) {
(($i < 3) or (!$rec)) or last;
push @popular, $rec;
$i++;
}
map { $popular .= &pop_link ($data{$_}) } @popular;
}
And when I actually use the data I use:
Code:
sub pop_link {
$ref = $data{$_};
$output = qq|$ref->{hits}\t$ref->{title}\n|;
return ($output);
}
Happy Coding,

--Drew
http://www.FindingHim.com
Quote Reply
Re: Perl sort question In reply to
Drew, thank's it works! Smile

DelPierro
http://www.simball.de/links_mods/
Quote Reply
Re: Perl sort question In reply to
Your welcome! Although I bet Mark or Alex could come up with something sexier Smile

Happy Coding,

--Drew
http://www.FindingHim.com
Quote Reply
Re: Perl sort question In reply to
i just thought you'd like to know junko.. your code skips every other line.. :)

MOD.. oh nevermind.. i thought while () { had <LOG> in it.. and it got "htmled" out

hmm....... sexy?

open LOG, "<hits.db";
while (<LOG>) {
next if /^\s*$/;
chomp;
my @data = split /\|/;
push ($data{$data[0]}, \@data);
}
close LOG;

map { $popular .= pop_link ($data{$_}) } (sort { $data->{$b}->[2] <=> $data->{$b}->[2] } keys %data)[0 .. 2];

Jerry Su
widgetz sucks
Quote Reply
Re: Perl sort question In reply to
Is it better to reference the filehandle like while(<FILE>) or does it matter? I used what was in my Perl book.

In Reply To:
hmm....... sexy?
Yes... packing as much function into a single line of code as posible. Smile

Happy Coding,

--Drew
http://www.FindingHim.com
Quote Reply
Re: Perl sort question In reply to
well.. i took a perl class.. and the teacher taught it that way.. he also said.. the best code is code not using last; end; next; and all those other ones.. but i tend to use next (for checking), return (to return something), and exit sometimes for shutdown commands..

Jerry Su
widgetz sucks
Quote Reply
Re: Perl sort question In reply to
hey.. you can have perl scripts with only 2 lines.. (shebang and code) that does a lot of stuff.. i've seen code in that form images of things too.. i've seen a program where all the lines of code formed a dolphin.. and the program ran well.. its cause spacing really doesn't matter in perl.. everything is s/\s+//g

Jerry Su
widgetz sucks