in reply to Re^5: Sorting based on any column
in thread Sorting based on any column

UPDATE: Thanks to AnomalousMonk for catching my mistake in forgetting that map needed to return a reference to the new array. Corrected in the code below. Also, he has a very nice way to handle the sorting choice; check that out in his reply.

1. In split you have specified ' ' which means it will split on single space, but in reality it splits for any number of space.

Right, that's a special case for split, which splits on any whitespace. That usually works well unless you need something more specific -- say, if your fields are separated by tabs but can include spaces. If you need to split on a specific type or amount of whitespace, adjust the first argument to split accordingly.

2. How can I do it using 'Schwartzian transform', I am still novice in perl, please do not mind.

I wouldn't call that a novice-level technique; I probably used Perl for several years before creating a ST myself. You can find plenty of examples and tutorials on it. But basically, it goes something like this:

# in pseudo-code: for each element calculate the sorting value for that element put the original element and the sorting value into a 2-element list pass these 2-element lists to your sorting routine, which sorts based on the sorting value of each element for each element in the sorted list of 2-element lists pull out the original element # in perl, an example using the typical map/sort/map layout # to sort a list of numbers based on the return value of a # complex subroutine that calculates the number of primes # less than each number's 25th power: my @newarray = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [ $_ => n_primes_less_than_25th_power($_) ] } @oldarray;

The essence is that each element of @oldarray is passed to the map which does the complex calculation on that element and creates a 2-element array containing the original element and the calculated value. References to those are passed to the sort, which can then sort on the calculated values without needed to recalculate them for every comparison. The sorted references then go to the map which just passes on the original values.

Your case would look much like this, except that instead of calling my n_primes...() subroutine, you'd have some code (or a call to a subroutine) in that location that parses out the value on which you want to sort. The first element $_->[0] would be the line, and the second element $_->[1] would be the parsed-out value for sorting.

Aaron B.
Available for small or large Perl jobs and *nix system administration; see my home node.

Replies are listed 'Best First'.
Re^7: Sorting based on any column
by AnomalousMonk (Archbishop) on May 21, 2015 at 14:27 UTC
    my @newarray = map { $_->[0] }
                   sort { $a->[1] <=> $b->[1] }
                   map { $_ => n_primes_less_than_25th_power($_) }
                 @oldarray;

    The essence is that each element of @oldarray is passed to the map which does the complex calculation on that element and creates a 2-element array containing the original element and the calculated value. Those are passed to the sort ...

    There's a big problem here. The first map expression must return a reference to a two-element array to pass to sort:
        map { [ $_ => n_primes_less_than_25th_power($_) ] }

    Note that the the  => (fat comma) in the above expression is just an idiosyncratic variation on the more common  , (comma) operator, so another version of the expression might be:
        map [ $_, n_primes_less_than_25th_power($_) ],
    (which also dispenses with the enclosing  { ... } code block (update: because  [ ... ] is a simple expression); note this needs a terminating comma operator).

    One way to easily control sort order is to realize that the  <=> and  cmp operators (see perlop) return (-1, 0, 1) as the result of their comparisons. If you have a scalar  $order that may have only the values 1 (ascending) or -1 (descending), it's easy to control ordering:
        sort { $order * ($a->[1] <=> $b->[1]) }
    (among other ways, of course).

    For tutorials on sorting and transformation sorts, see List Processing, Filtering, and Sorting, and in particular Understanding transformation sorts (ST, GRT), the details. See also A Fresh Look at Efficient Perl Sorting for an in-depth discussion of ST and GRT sorting.


    Give a man a fish:  <%-(-(-(-<