[sorry, PINE has become very confused about who said what]

On Oct 3, Jay Savage said:

On 10/3/05, Bakken, Luke <[EMAIL PROTECTED]> wrote:
JupiterHost.Net wrote:
>> On Oct 3, JupiterHost.Net said:
>>
>>> I have a list of strings that start with an uppercase B, Q, or Z
>>>
>>> I need to sort them so they are in order of Q, B , then Z
>>>
>>> Any ideas or input on how to efficiently do that with sort() or even
>>> map() is most appreciated :) perldoc -f sort|-f map didn't appear to
>>> address this situation :(
>
> Jeff 'japhy' Pinyan wrote:
>
>> I would use map() before and after sort() to "correct" leading
>> characters.
>>
>>   my @sorted =
>>     map { tr/123/QBZ/; $_ }
>>     sort
>>     map { tr/QBZ/123/; $_ }
>>     @data;
>
> Xavier Noria wrote:
>
>  > They all go in ASCII relative order except B <-> Q, thus a way to
>  get > it is to handle that special case and delegate to cmp the rest:
>  >
>  >     my @sorted = sort {
>  >         my $x = substr($a, 0, 1) . substr($b, 0, 1);
>  >         $x eq "BQ" || $x eq "QB" ? $b cmp $a : $a cmp $b;
>  >     } @array;
>  >
>  > I used the concatenation for clarity, you see the idea anyway if
>  that's > too expensive for your usage.
>
> Brilliant! I'll benchmark those ideas :) Thanks you two!

> Read this for an explanation of Jeff's solution:
>
> http://en.wikipedia.org/wiki/Schwartzian_transform

That will slow you down a little with the capturing and substitution,
but is solves Jeff's problem with capital Q, B, or Z later in the
string. I'm not sure how it stacks up to Xaiver's temp variable and
multiple substr calls. This isn't as simple as it looked.

Actually, I'm using a Guttman-Rosler Transform, not a Schwartzian Transform. I've actually come up with a slightly less "dangerous" technique I believe:

  my @sorted =
    map substr($_, 1),
    sort
    map +{qw( Q a  B b  Z c )}->{substr($_, 0, 1)} . $_,
    @original;

Reading from the bottom up:

1. we have the original array
2. using an anonymous hash reference ({Q => 'a', B => 'b', Z => 'c'}), we
   select the first character (Q, B, or Z) of the string ($_) and prepend
   the value in the hash corresponding that character (a for Q, b for B,
   or c for Z)
3. we then sort the modified list of words, with all the 'Q' words being
   first (since they are now prepended with 'a'), then all the 'B' words,
   then all the 'Z' words
4. then we extract everything AFTER the first character

--
Jeff "japhy" Pinyan        %  How can we ever be the sold short or
RPI Acacia Brother #734    %  the cheated, we who for every service
http://www.perlmonks.org/  %  have long ago been overpaid?
http://princeton.pm.org/   %    -- Meister Eckhart

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to