Ordering Values...

I am working on a script to process entries from a form and print out an address book, it doesn't hve to be particularly effective but I want to be able to print out 2 files, the first ordered by name, the second ordered by town...

The values are currently passed out into a control file, delimeded by |%%| with each entry on a new line e.g.

add0|%%|$add1|%%|$add2|%%|$add3|%%|$add4|%%|$add5

As I said I would want to print out 2 files, one with each line listed by name (add0) in alphabetical order, the second listed by town (add5) in alphbetical order...
JavaBloggsAsked:
Who is Participating?
 
maneshrConnect With a Mentor Commented:
here is a perl based solution for sorting your file and getting the results.

The advantages of this method are as follows :-

* based entirely in PERL. therefore portable.
* can be used to sort of ANY column.
* sort can be specified (alphabetical or numeric.)
* sort order can be specified (ascending or descending)
* modular, therfore can be used in ANY other program.

Add the code after all your processing is done. i.e. after....

print CTRL
"$add0|%%|$add1|%%|$add2|%%|$add3|%%|$add4|%%|$add5|%%|$add6|%%|$add7|%%|$add8|%%|$add9\n";
close(CTRL);

## PERL code to sort and store.
$GABctrl_by_name="gabctrl_by_name.dat";
$GABctrl_by_town="gabctrl_by_town.dat";

open(CTRL, "$GABctrl") or explode ("Cannot open control file at line ?? - $!");
@GAB=<CTRL>;  ## Read the entire file in an array!!
close (CTRL);


@GAB_by_name=&my_sort(2,"a","a",@GAB); ## Assuming name is the 2nd col, do a alphabetical ascending order sort.
@GAB_by_town=&my_sort(3,"a","d",@GAB); ## Assuming town is the 3rd col, do a alphabetical descending order sort.

## Write the output to the respective files!!
open(CTRL, ">$GABctrl_by_name") or explode ("Cannot open control file at line ?? - $!");
foreach(@GAB_by_name){
  print CTRL $_;
}
close(CTRL);

open(CTRL, ">$GABctrl_by_town") or explode ("Cannot open control file at line ?? - $!");
foreach(@GAB_by_town){
  print CTRL $_;
}
close(CTRL);

###############################################
##  Subroutine that does the actual sort.
##  Accepts 4 params viz. the column number to sort
##  Subroutine that does the actual sort.
##  Accepts 4 params viz. the column number to sort
##  Column no starts with 1. The type of sort numeric or alphabetic
##  Finally the sort order is required. Default order is ascending
##  The array that needs to be sorted.
sub my_sort{
  ($col,$type,$sort_order,@arr)=@_;

  ##  Deduct 1 from the column.
  ##  We do this because in PERL array subscript starts with 0.
  ##  So in human terms when we say column 2 it means column 1 in PERL terms!!
  $col--;

  ##  To take care of conditions where user has passed anything other
  ##  ... than a "n" or "N". Eg. if the user has said &my_sort(3,"z","a",@array), we ignore the z and perform an alphabetic sort ("a").
  $type="a" if $type!~ /^n$/i;  ##  Default Alphabetic sort

  ##  To take care of conditions where user has passed anything other
  ##  ... than a "d" or "D". Eg. if the user has said &my_sort(3,"z","q",@array), we ignore the q and sort in ascending order("a").
  $sort_order="a" if $sort_order!~ /^d$/i;  ##  Default Ascending Sort order

  ##  Process every element of the array
  foreach(@arr){
    ##  Split every line using , as the delimiter.
    @tmp=split(/\|%%\|/,$_);
    ##  After we split we know how many columns are ..
    ##  ... present in every record. Now we have to ...
    ##  ... take care of situations where the user might want ..
    ##  ... to sort on non-existant or invalid columns.
    ##  Eg. Each record has 6 columns and the user has passed 7 or 8
    ##  ... or -1 etc...

    return 0 if ($col<0 || $col>(scalar @tmp)); ## Invalid col no.

    ##  This is important. We take the column that the user wants ...
    ##  ... to sort on and pre-pend it to the record itself.

    ##  Let's say the record is ...
    # Toronto|%%|Jeff|%%|jeff@hyrum.net|%%|98|%%|571803
    ##  ...& the user wants to sort on the 2nd column (PERL subscript 1).
    $new_arr=join('|%%|',$tmp[$col],$_);
    ##  After the above the record will be...
    # Jeff|%%|Toronto|%%|Jeff|%%|jeff@hyrum.net|%%|98|%%|571803

    ##  Store this new record in an array
    push(@new_arr,$new_arr);
  }

  ##  Determine the type of sort
  if ($type=~ /^n$/i){    ##  Numeric Sort
    if ($sort_order=~ /^d$/i){  ##  Descending sort requested
      ##  Sort the array by number using the bynum subroutine
      @new_arr=reverse sort bynum @new_arr
    }else{  ##  Default, Ascending sort order requested
      @new_arr=sort bynum @new_arr
    }
  }else{  ##  Alphabetic sort
    if ($sort_order=~ /^d$/i){  ##  Descending sort requested
      ##  Sort the array by alphabets using the byalp subroutine
      @new_arr=reverse sort byalp @new_arr
    }else{  ##  Default, Ascending sort order requested
      @new_arr=sort byalp @new_arr
    }
  }

  undef @arr;
  ##  Remember our sort is done, but we still have that...
  ##  ...extra column at the beggining that we must remove!!
  foreach(@new_arr){
    ##  Split every line using , as the delimiter.
    @tmp=split(/\|%%\|/,$_);
    shift(@tmp);  ##  Remove that 1st column
    ##  So before the shift if we had....
    # Jeff|%%|Toronto|%%|Jeff|%%|jeff@hyrum.net|%%|98,571803
    ##  After th shift we will have...
    # Toronto|%%|Jeff|%%|jeff@hyrum.net|%%|98|%%|571803

    ##  Join the array as one record...
    $new_arr=join('|%%|',@tmp);
    ##  ...& store it in another array.
    push(@arr,$new_arr);
  }

  ##  Return the final array (in sorted order)
  return @arr;
}

sub bynum{ $a <=> $b;}

sub byalp{ $a cmp $b;}
0
 
maneshrCommented:
i am not clear of your exact requirements.

i have a couple of Q's for you.

* so do you already have a file where you have stored the users info and now you want to sort that same file and write the output to 2 diff files (one by name & other by town)??

* or do you want to take users input from the HTML form, store it in a file and then create 2 files, one sorted by name and other by town??

Also can you provide a sample file, if you have one??

Rgds
0
 
JavaBloggsAuthor Commented:
Okay...
I wanna take users input from HTML and store it in a file and then create the 2 ordered files from that...

What I have got so far is:
#!/bin/perl

print "Content-type: text/html\n\n";

$GABpage="http://www.gen.hobsons.com/forum/book.shtml";
$GABssif="results.htm";
$GABctrl="gabctrl.dat";

&parse_form;

$red=$ENV{'HTTP_REFERRER'};
$red="$GABpage";

$method=$ENV{'REQUEST_METHOD'};
if ($method !~ /POST/i) {
  print "Location: $red\n\n";
  exit;
}

open(CTRL, "<$GABctrl") or explode ("Cannot open control file at line 21 - $!");
      push @contents, <CTRL>;
close(CTRL);

$add0 = $FORM{'Title'};
$add0 =~ s/(\n|\r|\t)/ /isg;
$add1 = $FORM{'Firstname'};
$add1 =~ s/(\n|\r|\t)/ /isg;
$add2 = $FORM{'Surname'};
$add2 =~ s/(\n|\r|\t)/ /isg;
$add3 = $FORM{'Jobtitle'};
$add3 =~ s/(\n|\r|\t)/ /isg;
$add4 = $FORM{'Field'};
$add4 =~ s/(\n|\r|\t)/ /isg;
$add5 = $FORM{'company'};
$add5 =~ s/(\n|\r|\t)/ /isg;
$add6 = $FORM{'Region'};
$add6 =~ s/(\n|\r|\t)/ /isg;
$add7 = $FORM{'Country'};
$add7 =~ s/(\n|\r|\t)/ /isg;
$add8 = $FORM{'Business'};
$add8 =~ s/(\n|\r|\t)/ /isg;
$add9 = $FORM{'Email'};
$add9 =~ s/(\n|\r|\t)/ /isg;

open(CTRL, ">>$GABctrl") or explode ("Cannot open control file at line 45 - $!");
      print CTRL "$add0|%%|$add1|%%|$add2|%%|$add3|%%|$add4|%%|$add5|%%|$add6|%%|$add7|%%|$add8|%%|$add9\n";
close(CTRL);

Sorry, know its not great  :o(  just generates a file I can perorm a split on...

0
Take Control of Web Hosting For Your Clients

As a web developer or IT admin, successfully managing multiple client accounts can be challenging. In this webinar we will look at the tools provided by Media Temple and Plesk to make managing your clients’ hosting easier.

 
geotigerCommented:
Although it is not a pure Perl answer, it will serve your purpose assuming you are working in a unix environment:
$fn = "/full/dir/to/your/addr/file";
$out_fn1 = "/output/file/name1";
$out_fn2 = "/output/file/name2";

$sort_byname = "cat $fn | sort ";

open FILE, "$sort_byname |" or die "could not run $sort_byname:$!\n";
open OUT1, ">$out_fn1" or die "could not write to $out_fn1:$!\n";
while (<FILE>) { print OUT1 $_; }
close FILE;

$sort_bytown = "cat $fn | sed -e 's/\|\%\%\|/\|/g' | sort -t\| -k 6,6 ";
open FILE, "$sort_bytown |" or die "could not run $sort_bytown:$!\n";
open OUT2, ">$out_fn1" or die "could not write to $out_fn2:$!\n";
while (<FILE>) { print OUT2 $_; }
close FILE;

If you are looking for pure Perl, solution, you need to use "cmp" function to do the comparison.

0
 
geotigerCommented:
Forgot to close the two output files. Please add the following:

close OUT1;
close OUT2;

0
 
JavaBloggsAuthor Commented:
Thanks very much for that one...

Its working brilliantly, and I lernt a fair bit from it  :o)

There was one minor problem, its academic now as I have split the processes up, but the second ordered set your code put out had the entries in twice (presumably because @new_arr still had the old values in it)...

Regards
From
Me
!

0
 
maneshrCommented:
"......There was one minor problem, its academic now as I have split the processes up, but the second ordered set your code put out had the entries in twice (presumably because @new_arr still had the old values in it)... ...."

Sorry. my mistake!! :-0



Pl. add the foll line........

undef @new_arr;

BEFORE....

##  Return the final array (in sorted order)

that should fix it.

Rgds
0
 
JavaBloggsAuthor Commented:
Nice one, cheers yet again  :o)

It is now happy, bouncy, funkey and cool... and will keep me going till I get SQL sorted  :o)

Regds
me
0
 
maneshrCommented:
Cool!!

Wish you luck with your project!!

Rgds
0
All Courses

From novice to tech pro — start learning today.