in reply to Notation of sort function

It's a good question. There are cases where one might want to apply different conditions on the operands or where one of the operands isn't $a or $b at all. These cases are rare but they do crop up from time to time.

I have had a trawl through some code of mine and haven't found one yet. Closest I have is this:

@abc = sort { length ($b) <=> length ($a) || $a cmp $b } @abc;

Even through here we are treating $a and $b in the same way, I don't know how you would express this without the flexibility that the current syntax gives. It would not be as succinct, that's for sure.


🦛

Replies are listed 'Best First'.
Re^2: Notation of sort function
by Discipulus (Canon) on Oct 27, 2023 at 10:43 UTC
    Hello all,

    Alphaphi: I dont see redundancy, I think the syntax is flexible to permit also different use cases.

    hippo:

    > There are cases where one might want to apply different conditions on the operands..

    mmh.. yes this can also be true but I suppose just as a trigger inside comparison: which apple is heavier but golden one count more

    use strict; use warnings; use Data::Dump; my %apples = ( one => { weight => 10, golden=> 0}, two => { weight => 20, golden=> 0}, three => { weight => 5 , golden=> 1}, ); my @sorted = sort{ ( $apples{$b}->{golden} ? $apples{$b}->{weight} * 10 : $apples{$b}->{weight} ) <=> ( $apples{$a}->{golden} ? $apples{$a}->{weight} * 10 : $apples{$a}->{weight} ) }keys %apples; dd @sorted; __END__ ("three", "two", "one")

    > ..or where one of the operands isn't $a or $b at all

    I dont think this can be logic. Also in sort of misunderstanding of sort you can find that sort is optimized, so not every pair is checked so if you will sort apple against pear I wonder which use case can be.

    Courious to know otherwise :)

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      I dont think [one of the operands isn't $a or $b at all] can be logic.

      Here is one example. In the case where you just want all values which meet some criterion moved to the beginning or end of the list then you can do something like this:

      #!/usr/bin/env perl use strict; use warnings; my @words = qw/The omega quick brown omega fox jumps over the omega la +zy dog/; my @sorted = sort { $a eq 'omega' ? 1 : -1 } @words; print "@sorted\n";

      This moves all the 'omega' entries to the end of the array but the other entries are not predictably sorted. Not something you are going to need every day but useful to have in the toolbox for those rare occasions which call for it.


      🦛

      This is a good example for redundancy. Why not like this:
      my @sorted = sort{ { $apples{$SORTVAR}->{golden} ? $apples{$SORTVAR}->{weight} * 10 : $apples{$SORTVAR}->{weight} }, '<=>' } keys %apples;
      Here I specify the calculation to be performed only once, and as a second parameter, I pass the operator.

        There is:

        use List::AllUtils qw( nsort_by ); my @sorted = nsort_by { $apples{$_}->{golden} ? $apples{$_}->{weight} * 10 : $apples{$_}->{weight} } keys %apples;

        There is also a string compare version.

        The special variables $a and $b are also used to specify order. Here's a very simple example:

        $ perl -E ' my @x = (23, 12, 45); say "Unsorted:"; say for @x; say "Ascending:"; say for sort { $a <=> $b } @x; say "Descending:"; say for sort { $b <=> $a } @x; ' Unsorted: 23 12 45 Ascending: 12 23 45 Descending: 45 23 12

        How would you implement that in your hypothetical syntax?

        — Ken

        use Sort::Key qw( nkeysort ); my @sorted = nkeysort { $apples{ $_ }{ weight } * ( $apples{ $_ }{ golden } ? 10 : 1 ) } keys( %apples );