in reply to Re^4: Building a sorting subroutine on the fly
in thread Building a sorting subroutine on the fly
All depends on how abstract you want to get. Given that you want "the keyboard operator [to be able to] modify it easily," I'd say that you may want it as abstract as possible.
#!/usr/bin/perl use strict; use warnings; my @cols = qw ( lastname firstname cno unit ward dateadmission datebirth ); my %cols_idx = do { my $i = 0; map { $_ => $i++ } @cols }; 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 ) ], ); sub make_single_comparator { print "parms: @_\n"; my $data = shift; my $col = shift; my $asc = shift; my $type = shift; my $idx = $cols_idx{$col}; print "idx: $idx\n"; my %subs = ( U => { a => sub { $a->[$idx] cmp $b->[$idx] }, n => sub { $a->[$idx] <=> $b->[$idx] }, # s??? not sure what you mean by 's' ... feel fre +e to # modify this. 's' => sub { $a->[$idx] cmp $b->[$idx] }, }, D => { a => sub { $b->[$idx] cmp $a->[$idx] }, n => sub { $b->[$idx] cmp $a->[$idx] }, # same problem as above. 's' => sub { $b->[$idx] cmp $a->[$idx] }, }, ); $subs{$asc}{$type}; } sub sort_maker { my @subs = @_; sub { foreach my $sub (@subs) { my $result = $sub->(); # you use $a and $b in your littles +ubs - no need to pass in globals. return $result if $result; } } } sub sort_by_column { my $data = shift; my @order = @_; my $sortref = sort_maker( map { make_single_comparator( $data, $_, @{$parameters{ +$_}} ); } @order ); my @results = sort $sortref @$data; @results } my @data = map [ split " " ] => <DATA>; use Data::Dumper; print Dumper [sort_by_column(\@data, @ARGV ? @ARGV : qw{ lastname firs +tname cno } )]; __DATA__ 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
As you notice, much of the error checking (that parms are actually allowed - e.g., 'foo' isn't a table header) is missing. Feel free to add.
Also, rather than a big hash, you could build it up using an eval STRING. Up to you - I'm using a large closure instead to probably reduce memory, probably reduce runtime, and definitely reduce the ability for me to screw it up security-wise. That said, I do think that this is probably a scenario that could be made secure for an eval STRING, especially if you start getting many more options on how to do things and those start combining to give exponential degrees of freedom. Here there are only six possible comparators, which is easy enough to hardcode ahead of time. More generically, an eval STRING may ease development and maintenance.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^6: Building a sorting subroutine on the fly
by jkeenan1 (Deacon) on Nov 30, 2005 at 00:54 UTC | |
|
Re^6: Building a sorting subroutine on the fly
by jkeenan1 (Deacon) on Dec 31, 2005 at 03:27 UTC |