>>>>> "AS" == Aaron Sherman <[EMAIL PROTECTED]> writes:
AS> On Thu, 2004-02-12 at 15:46, Uri Guttman wrote:
>>
>> how do you select descending order? and how do you selecte that per
>> key?
>> you can't provide a binary operator without also providing the
>> order. and what about different key types? the <=> and cmp
>> operators are not enough information needed to do complex
>> sorts. collating sequences are another issue. you need to have that
>> info on a perl key basis.
AS> I think my example addressed all of your concerns, and did it in Perl 5.
AS> Once again, that was:
AS> sub sortpairs(&@) {
AS> my $comp = shift;
AS> my %pairs = @_;
AS> return map {$pairs{$_}} sort {$comp->()} keys %pairs;
AS> }
AS> @new1 = sortpairs {$a <=> $b} map {($_->computekey,$_)} @old1;
AS> @new2 = sortpairs {$a cmp $b} map {(lc($_),uc($_))} @old2;
AS> So, in order, your questions were:
AS> * how do you select descending order?
AS> You reverse the $a and $b in the first parameter to sortpairs
i find that a poor solution. the $a cmp $b isn't needed in the ascending
case at all. a descending marker per key is better as it reflects the
results desired and not how it gets done. the reversing of $a and $b
requires the coder to understand sort comparison callbacks. it is
implementation exposed.
AS> * and how do you selecte that per key?
AS> Ok, I was only addressing one key. But, it's not hard to
AS> generalize the idea, and certainly Perl 6 gives you the tools to
AS> do so easily.
i haven't seen any proposals other than mine (which is bad syntax but
good semantics) for this. and if you have multiple keys with each having
a $a <=> $b in there it will be very noisy.
AS> * you can't provide a binary operator without also providing the
AS> order.
AS> Correct
a single descending marker is simpler and better semantics.
AS> * and what about different key types? the <=> and cmp operators
AS> are not enough information needed to do complex sorts.
AS> That's fine, you can plug in a call to Alien::Headed::Babies
AS> inside the closure for all I care.
there are only a short list of key comparisons possible, int, string,
float and maybe unicode. i separate int from float since they do have
different internals in the GRT. it is one area where you do expose
stuff. otherwise you could just use number.
AS> * collating sequences are another issue. you need to have that
AS> info on a perl key basis.
AS> Give me an example?
simple. pick almost any language char set other than US ascii. many have
special collating sequences. i am not anything close to a unicode expert
but i have seen this issue. in fact setting the LANG (or some other)
environment variable will affect many programs by changing the collating
order.
AS> * multiple keys with each having different comparisons and
AS> different sort orders.
AS> Ok let's delve into it then:
AS> sub sortpairs(&@){
AS> my $comp = shift;
AS> my @elements = @_;
AS> return map {my $e=$elements[$_];$e->[$#{$e}]} sort {
AS> my @akeys = @{$elements[$a]}[0..$#{$elements[$a]}-1];
why the -1? that looks like:
my @akeys = @{$elements[$a]} ;
pop @akeys ;
pop @akeys ;
AS> my @bkeys = @{$elements[$b]}[0..$#{$elements[$b]}-1];
AS> for(my $i=0;$i<@akeys;$i++) {
AS> my $dir = $comp->($akey[$i],$bkey[$i]);
AS> return $dir if $dir;
AS> }
AS> return 0;
AS> } 1..scalar(@elements);
AS> }
that is scary. do you realize that the sort block will be called for
each comparison?
AS> @new1 = sortpairs {$_[0] <=> $_[1]} map {[$_,$_]} @old1;
AS> @new2 = sortpairs {$_[0] <=> $_[1] || $_[4] cmp $_[3]} map
AS> {[getkeys($_),$_]} @old2;
where is getkeys defined? how do you know what indexes to use for each
comparison? what happened to $_[2]? your call to $comp is passed 2
arguments but the second example accesses 4 arguments.
AS> The second example really illustrates the point that you can swap the
AS> direction of key order and mechanism to compare them at your whim.
AS> Now, you just need to call sortpairs with any array of arrays of keys
AS> (with trailing value).
add a third key to that. quickly!
a more straightforward api (which is close to what i will do in
Sort::GRT) is (p5 code)
my $sort = Sort::GRT->new(
keys => [
{ descending => 1,
type => float,
extract => '$_->{amount},
},
{ extract => 'substr( $_->{date}, 0, 4)' },
]
) ;
my @sorted = $sort->do_it( @unsorted ) ;
$sort->do_it_inplace( [EMAIL PROTECTED] ) ;
add a third key:
my $sort = Sort::GRT->new(
keys => [
{ descending => 1,
type => float,
extract => '$_->{amount}',
},
{ extract => 'substr( $_->{date}, 0, 4)' },
{ extract => '$_->{user}{last_name}' },
]
) ;
see? no issues with || or <=> or order or $_[4]. each key must have its
own type, order and extract code. the logical way to do that is a list
of hashes which is easy to describe and create a syntax for in p6. all
the other proposals i have seen here bypass this need for multikey
support.
uri
--
Uri Guttman ------ [EMAIL PROTECTED] -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org