Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

sort a file by field 2

Status
Not open for further replies.

IWIT

Vendor
Mar 5, 2004
13
0
0
GB
Hi

I have a problem with a perl program that I have been writing. I have so far managed to pass in the contents of an external file and have it displayed on the screen in a structured way. The file is meant to be a bit like a message board. I now want to sort the messages by a certain field such as email, name or subject but I am completely unsure on how to do this. I know that I need to use the Sort function but everytime I try and use this it doesnt work. I have copied below the code that works for the displaying of the file.

#!/usr/bin/perl
use strict;
use warnings;
use CGI "Vars";

my ($filename, @all, $list, @items, $item);


$filename = "msgs";

open(MYFILE,"< $filename");
@all=;

$list ="@all";
@items = split /__FINISH__\n/ , $list;


for my $item (@items)
{
my($name, $email, $subject, $text) =split /\n/, $item, 4;

print "Name:- $name\n";
print "Email:- $email\n";
print "Subject:- $subject\n";
print "Message:- $text\n";
}

Thank You
 
Basically you put the data in hashes and assign a unique id to it so you can have multiple per user or subject then do the sort on that ...I'll show the by email below (note that if you're sorting on ascii then use "cmp" and if it's numeric like a length or whatever then use "<=>"

hope this works for you...

Code:
my ($filename, @all, $list, @items, $item);


$filename = "msgs";

open(MYFILE,"< $filename");
@all=<MYFILE>;

$list ="@all";
@items = split /__FINISH__\n/ , $list;


$sortby="email";

for my $item (@items)
{

    $uniqueId++;

my($name, $email, $subject, $text) =split /\n/, $item, 4;

    $nameOf{$uniqueId}=$name;
    $emailOf{$uniqueId}=$email;
    $subjectOf{$uniqueId}=$subject;
    $textOf{$uniqueId}=$text;
}


foreach $id (sort by_email keys %nameOf) {
    print "Name:- $nameOf{$id}\n";
    print "Email:- $emailOf{$id}\n";
    print "Subject:- $subjectOf{$id}\n";
    print "Message:- $textOf{$id}\n";
} 

sub by_email {
    $emailOf{$a} cmp $emailOf{$b};
}
 
I tried to do it the way above but it didnt work. I then tried to use annonymous hashes to sort the file and I think its almost there. I think there is just a minor problem with the sort line. I think I may have mixed up the variables or something like that. Dunno if any of you guys can see any major mistakes.

#!/usr/bin/perl
use strict;
use warnings;
use CGI "Vars";

my ($filename, @all, $list, @items, $item);
$filename = "msgs";

open(MYFILE,"< $filename");
@all=<MYFILE>;
$list ="@all";
@items = split /__FINISH__\n/ , $list;

my $h; my @LoH;
foreach $item (@items)
{
($h->{name}, $h->{email}, $h->{subject}, $h->{text}) = split /\n/, $item,4;
push @LoH,$h;
}


#I think this is the line with problems#
for $h (sort { $a->{name} cmp $b->{name} @LoH) {
print "Name:- $h->{name}\n";
print "Email:- $h->{email}\n";
print "Subject:- $h->{subject}\n";
print "Message:- $h->{text}\n";

}
}

And the errors I get are:

Array found where operator expected at ./sort line 23, near "} "
(Missing operator before ?)
syntax error at ./sort line 23, near "} @LoH"
syntax error at ./sort line 25, near "print"
Execution of ./sort aborted due to compilation errors.
 
You're missing a closing curly brace before "@LoH", to close off the sort block.
Should be
for $h (sort { $a->{name} cmp $b->{name} } @LoH)
 
Thank You

The program is now working without errors but it now displays five copies of the same record.
 
I've figured out now that I was sorting more than once within the for loop but i'm still getting out five copies of the same record rather than one copy of each of the five records in whatever order they may have been sorted into. If this helps at all the record that keeps appearing is the last one in the unsorted data file. Anymore help would be much appreciated.

Code:
my $h; my @LoH;
foreach  $item (@items)
{
  ($h->{name}, $h->{email}, $h->{subject}, $h->{text}) = split /\n/, $item,4;
  push @LoH,$h;
} 

@sorted= sort { $a->{name} cmp $b->{name} } @LoH; 

for $sorted (@sorted)
{
print "Name:- $sorted->{name}\n";   
print "Email:- $sorted->{email}\n";   
print "Subject:- $sorted->{subject}\n";   
print "Message:- $sorted->{text}\n"; 


}
 
%h is a hash, so it needs to be declared that way. (You're declaring it as a scalar.) Then you want to push a reference to that hash into @LoH. (Note the curlies around %h in push statement to create a ref.)
Code:
my %h; # %h is a hash
my @LoH;
foreach  $item (@items)
{
  ($h{name}, $h{email}, $h{subject}, $h{text}) = split /\n/, $item,4; # split to hash
  push @LoH, { %h }; # push ref to hash
}
 
Absolute genious!

I think thats it now working. Thats the thing I hate about programming, one small change and it works.

Cheers.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top