my $mysortref = sort_maker( sub { lc($data{$a}[0]) cmp lc($data{$b}[0]) }, sub { lc($data{$a}[1]) cmp lc($data{$b}[1]) }, ); @results = sort $mysortref (keys %data); print "@{$data{$_}}\n" for (@results); sub sort_maker { my @littlesubs = @_; sub { foreach my $sub (@littlesubs) { my $result = $sub->(); return $result if $result; } }; }
It's left as an excersise to the reader on how to convert your query language into perl sort functions. Translation: I'd help further, but I don't know how you know what order to sort in.
Let me explain the context and interface desired. Returning to my original data sample will be illustrative. Suppose that I have data stored in plain-text files, one record per line, fields delimited by whitespace:
HERNANDEZ HECTOR 456791 SAMSON 0217 2001-07-25 1963-08-0 +1 VASQUEZ JOAQUIN 456789 SAMSON 0209 1990-11-14 1970-03-2 +5 JONES TIMOTHY 803092 LAVER 0103 2001-03-19 1969-06-2 +9 SMITH BETTY_SUE 698389 SAMSON 0211 1992-01-23 1949-08-1 +2
Suppose further that the columns in this table may be named:
lastname firstname cno unit ward dateadmission datebirth
And suppose further that I have a hash (probably stashed in a configuration file) which associates those column names with array elements specifying the order and type of searches to be conducted on each column (i.e., ascending or descending order; alphabetical, ASCII-betical or numerical type). That hash might look like this:
... where U and D are up and down; a, s and n are the 3 search types.my %parameters = ( lastname => [ qw( U a ) ], firstname => [ qw( U a ) ], cno => [ qw( U n ) ], unit => [ qw( U s ) ], ward => [ qw( U n ) ], dateadmission => [ qw( D a ) ], datebirth => [ qw( D a ) ], );
Assuming that the data and the column parameters have been used to initialize an object $dp, I want the user to be able to call a method:
my $results_ref = $dp->sort_by_column( qw{ lastname firstname cno } );
... and have $results_ref hold an array of arrays where the outer array is sorted in the order specified in the arguments to sort_by_column. That is, the method will sort the data in the order and using the search-type specified by the column name.
Under normal circumstances, the user (a cron job or a keyboard operator) will run the same script with the same method calls and arguments every day. But from time to time the database administrator will have to prepare new queries in which, for example, the dates have to be reported in ascending order, rather than descending as in the above. The administrator would then prepare a different %parameters, but the method call would either not change or change so little that the keyboard operator could modify it easily.
In short, the objective is to go from a list of column names to an array of sort formulas each represented by an anonymous subroutine. If lastname is the first column in the table, then "Sort by last names, alphabetically and in ascending order," should translate into:
sub { lc($data{$a}[0]) cmp lc($data{$b}[0]) },
The question, then, is how to effect that translation. Thank you very much.
Jim Keenan
Update: Corrected 'readmore' error.
In reply to Re^4: Building a sorting subroutine on the fly
by jkeenan1
in thread Building a sorting subroutine on the fly
by jkeenan1
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |