T
Tassilo v. Parseval
Hi there,
I was in the situation to come up with a kind of special sort routine.
The data to be sorted is a list of fully qualified function names as in
Pack1::subpack::func2
Pack1::subpack::func1
Pack1::func
__MAIN__
Pack2::bla
Pack1::subpack::another_subpack::func
which ultimately should be sorted like this:
Pack1::func
Pack1::subpack::func1
Pack1::subpack::func2
Pack1::subpack::another_subpack::func
Pack2::bla
__MAIN__
So essentially this should order these functions hierarchicly on their
package name and finally on their function name. '__MAIN__' should
always come as last element.
I had a hard time getting it right for a seemingly simple problem such
as this one. My solution:
@sorted = sort bypackage @functions;
sub bypackage {
# make sure that __MAIN__ is always last on output
return 1 if $a eq '__MAIN__';
return -1 if $b eq '__MAIN__';
my @a = split /::/, $a;
my @b = split /::/, $b;
my $s = '$a[0] cmp $b[0]';
if (@a == @b) {
$s .= "||\$a[$_] cmp \$b[$_]" for 1 .. $#a;
} else {
my $min = @a < @b ? $#a : $#b;
$s = '$a[0] cmp $b[0]';
$s .= "||\$a[$_] cmp \$b[$_]" for 1 .. $min-1;
$s .= "||\@a <=> \@b";
}
return eval $s;
}
I am not so much concerned with the dog-like slowness of the above. That
can be tolerated (the splits could be be cached to improve it a little).
I think the wordiness doesn't make this a very elegant solution measured
by Perl-standards.
How would others solve this task?
Bonus question: if speed was an issue, how could techniques such as
the Schwartzian or Guttman-Rosler Transform be applied here?
Tassilo
I was in the situation to come up with a kind of special sort routine.
The data to be sorted is a list of fully qualified function names as in
Pack1::subpack::func2
Pack1::subpack::func1
Pack1::func
__MAIN__
Pack2::bla
Pack1::subpack::another_subpack::func
which ultimately should be sorted like this:
Pack1::func
Pack1::subpack::func1
Pack1::subpack::func2
Pack1::subpack::another_subpack::func
Pack2::bla
__MAIN__
So essentially this should order these functions hierarchicly on their
package name and finally on their function name. '__MAIN__' should
always come as last element.
I had a hard time getting it right for a seemingly simple problem such
as this one. My solution:
@sorted = sort bypackage @functions;
sub bypackage {
# make sure that __MAIN__ is always last on output
return 1 if $a eq '__MAIN__';
return -1 if $b eq '__MAIN__';
my @a = split /::/, $a;
my @b = split /::/, $b;
my $s = '$a[0] cmp $b[0]';
if (@a == @b) {
$s .= "||\$a[$_] cmp \$b[$_]" for 1 .. $#a;
} else {
my $min = @a < @b ? $#a : $#b;
$s = '$a[0] cmp $b[0]';
$s .= "||\$a[$_] cmp \$b[$_]" for 1 .. $min-1;
$s .= "||\@a <=> \@b";
}
return eval $s;
}
I am not so much concerned with the dog-like slowness of the above. That
can be tolerated (the splits could be be cached to improve it a little).
I think the wordiness doesn't make this a very elegant solution measured
by Perl-standards.
How would others solve this task?
Bonus question: if speed was an issue, how could techniques such as
the Schwartzian or Guttman-Rosler Transform be applied here?
Tassilo