?
Solved

Ordering Values...

Posted on 2000-05-15
9
Medium Priority
?
255 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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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 1140 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

[Webinar] Lessons on Recovering from Petya

Skyport is working hard to help customers recover from recent attacks, like the Petya worm. This work has brought to light some important lessons. New malware attacks like this can take down your entire environment. Learn from others mistakes on how to prevent Petya like worms.

Question has a verified solution.

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

A year or so back I was asked to have a play with MongoDB; within half an hour I had downloaded (http://www.mongodb.org/downloads),  installed and started the daemon, and had a console window open. After an hour or two of playing at the command …
In the distant past (last year) I hacked together a little toy that would allow a couple of Manager types to query, preview, and extract data from a number of MongoDB instances, to their tool of choice: Excel (http://dilbert.com/strips/comic/2007-08…
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
Suggested Courses

762 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