CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
Search Posts SEARCH
Who's Online WHO'S
Log in LOG

Home: Perl Programming Help: Beginner:
sort and print



Jan 7, 2001, 3:46 PM

Post #1 of 7 (894 views)
sort and print Can't Post


I have a database and want to print selected folders in alphabetical order (by surname or city). The database looks like this:

Folder|First name|Surname|City|Country
0|tom|smith|new york|usa

A user can select a folder number and sortby surname or city option, and then hit a print button.
e.g. selecting folder 2 and sorting by surname would print tina first then mary and nothing else. If city was the selected sort, then mary would be printed first then tina.

Does anyone have a piece of readymade code to do that for me? I have gone through all the past questions on this but am getting very confused. Your help would be greatly appreciated.



Jan 7, 2001, 7:14 PM

Post #2 of 7 (888 views)
Re: sort and print [In reply to] Can't Post

Here is a sorting routine:

@sortedarray = sort {lc($a) cmp lc($b)} @array;


User / Moderator

Jan 7, 2001, 9:21 PM

Post #3 of 7 (884 views)
Re: sort and print [In reply to] Can't Post

In this case we cannot just do a simple sort, or even a simple sort {$a cmp $b} because we need to actually be sorting on things from the middle of the strings.

This is a good time to use my favorite perl function, 'map', not just once, but twice, in a Schwartzian Transform. And because we need to filter the list down to just those that match the folder, we will throw in a grep also.

sub transform_sort { 
my ($folder, $option, @array) = @_;

my %index = (Folder => 0,
'First name' => 1,
Surname => 2,
City => 3,
Country => 4);

return (map { (split ('<->', $_))[1] }
map { join ('<->', lc ((split ('\|', $_))[$index{$option}]), $_) }
grep (/^$folder\|/ , @array)

Inside the return you must read from bottom to top as each line takes an array as input and passes it on to the command above it.

First grep takes the original @array and only passes on things that begin with $folder. Then the lower map finds the keyword that we want to search on and create an array of 'lc (keyword)<->original string'. Then these strings can pass through the normal boring everyday sort. And lastly we split on '<->' to get the original string back.

If you want to try it youself, here is the rest of my test...

#Folder|First name|Surname|City|Country 
my @array = ('0|tom|smith|new york|usa',

print ("\nThe original array is:\n ",
join ("\n ", @array),
"\nThe sorted array zanardi version:\n ",
join ("\n ", sort {lc($a) cmp lc($b)} @array),
"\nThe sorted array for (1, 'Surname')is:\n ",
join ("\n ", &transform_sort (1, 'Surname', @array)),
"\nThe sorted array for (2, 'Surname')is:\n ",
join ("\n ", &transform_sort (2, 'Surname', @array)),
"\nThe sorted array for (2, 'City')is:\n ",
join ("\n ", &transform_sort (2, 'City', @array)),
"\nThe sorted array for (2, 'First name')is:\n ",
join ("\n ", &transform_sort (2, 'First name', @array)),
"\nThe sorted array for (2, 'Country')is:\n ",
join ("\n ", &transform_sort (2, 'Country', @array)),


Jan 8, 2001, 2:33 PM

Post #4 of 7 (869 views)
Re: sort and print [In reply to] Can't Post


Thanks for the efforts you made to write the script. It works perfectly.

I would love to learn some time how it works!

One quick question though, is it possible to identify the variables in the final printed output? For instance, if I selected folder 3 and sort by Surname,would frank, conway, michael, and buckley each have different variable names, e.g. array[2].

The reason I ask is that I want to put each item individual item into a HTML table cell. Therefore, in the above example, I would have a 2 row and 5 column table. Would it be difficult for you to add this feature?

Once again, thanks for what you have done todate, it was excellent.


User / Moderator

Jan 8, 2001, 10:31 PM

Post #5 of 7 (863 views)
Re: sort and print [In reply to] Can't Post

&transform_sort will return an array of rows in your future table. But those rows will again be '|' delimited.

You can use this print statement to print a table with 5 columns and each row that fit already sorted, plus I added the header row at the top.

print ("\nThe sorted table for (3, 'Surname')is:\n<table>\n"); 

foreach ('Folder|First name|Surname|City|Country',
&transform_sort (3, 'Surname', @array)) {
print ('<tr>',
(map { "<td>$_</td>\n" } split ('\|', $_)),
print ("</table>\n");

The foreach loops through each row and and prints the '<tr>' tags. And then to get the individual columns we again split on '|' and wrap '<td>' tags around each cell.

To help see what the map is doing compare it to this version that uses foreach row around foreach column

print ("\nThe sorted table for (3, 'Surname')is:\n<table>\n"); 
foreach my $row ('Folder|First name|Surname|City|Country',
&transform_sort (3, 'Surname', @array)) {
print '<tr>';
foreach my $col (split ('\|', $row)) {
print "<td>$col</td>\n";
print "</tr>\n";


Jan 9, 2001, 6:31 AM

Post #6 of 7 (856 views)
Re: sort and print [In reply to] Can't Post

Thanks again rGeoffrey,

I will try the code tonight.

The reason I asked about identifying the variable is because I want to put a link on the surname (in addition to the table issue).

For instance, if the surname is murphy, the link would be murphy underlined. When someone clicks on the link, a script would be called
e.g. cgibin/

I will understand if this is too much to ask.

Take care,


User / Moderator

Jan 12, 2001, 8:45 PM

Post #7 of 7 (839 views)
Re: sort and print [In reply to] Can't Post

To make a slightly more complicated table cell you can get the columns for each row, and then replace the cell before you print it.

This will build the link you wanted...

print ("\nThe original array is:\n  ", 
join ("\n ", @array),
"\nThe sorted table for (3, 'Surname')is:\n<table>\n");

print ('<tr>',
(map {"<th>$_</th>\n"} split ('\|', 'Folder|First name|Surname|City|Country')),

foreach my $row (&transform_sort (3, 'Surname', @array)) {
my @cols = split ('\|', $row);
$cols[2] = "<a href=\"cgibin/$cols[2]&city=$cols[3]\">$cols[2]</a>";
print ('<tr>',
(map {"<td>$_</td>\n"} @cols),
print ("</table>\n");

Sun Sep 9, 2001 - 1:46:40 GMT, a very special second in the epoch. How will you celebrate?


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives