Solved

Ordering Values...

Posted on 2000-05-15
9
254 Views
Last Modified: 2010-03-05
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...
0
Comment
Question by:JavaBloggs
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
  • 2
9 Comments
 
LVL 16

Expert Comment

by:maneshr
ID: 2811368
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
 

Author Comment

by:JavaBloggs
ID: 2811421
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
 
LVL 12

Expert Comment

by:geotiger
ID: 2811508
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 12

Expert Comment

by:geotiger
ID: 2811521
Forgot to close the two output files. Please add the following:

close OUT1;
close OUT2;

0
 
LVL 16

Accepted Solution

by:
maneshr earned 285 total points
ID: 2811786
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
 

Author Comment

by:JavaBloggs
ID: 2813669
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
 
LVL 16

Expert Comment

by:maneshr
ID: 2813981
"......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
 

Author Comment

by:JavaBloggs
ID: 2814357
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
 
LVL 16

Expert Comment

by:maneshr
ID: 2814718
Cool!!

Wish you luck with your project!!

Rgds
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I've just discovered very important differences between Windows an Unix formats in Perl,at least 5.xx.. MOST IMPORTANT: Use Unix file format while saving Your script. otherwise it will have ^M s or smth likely weird in the EOL, Then DO NOT use m…
There are many situations when we need to display the data in sorted order. For example: Student details by name or by rank or by total marks etc. If you are working on data driven based projects then you will use sorting techniques very frequently.…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans

689 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question