in reply to sorting based on a list

Hmm. I just realized there's another interpretation of the question that might be more valid than my other solution.

Suppose the question means: given elements of @list2 which begin with the letters of @list, rearrange them so that the beginning letters are sorted in that order. Thus, the length of @list2 in no way correlates with the length of @list, and this was merely a concidence in the sample set.

To that, I'll have to add two arbitrary decisions: if the word doesn't begin with one of the letters, put it first, and within a given initial letter, sort alphabetically.

The code for that would look like this:

my %mapping; @mapping{@list} = 1..@list; my @rearranged = map { $_->[0] } sort { $a->[1] <=> $b->[1] or $a->[0] cmp $b->[0] } map { [$_, $mapping{substr($_,0,1)} || 0] } @list2;
There. One of them there, Schwartzian thingies.

And yes, I see other similar solutions in this thread, but I bet those repeated index() calls inside the sort comparator are gonna make it doggy slow for dozens of elements. By caching the reverse map, as well as the sort position, we save mondo time.

-- Randal L. Schwartz, Perl hacker

Replies are listed 'Best First'.
Re: Re: sorting based on a list
by ChemBoy (Priest) on May 09, 2001 at 20:01 UTC

    And here, for completeness, is a (presumably much slower) solution based on the opposite assumptions (extra letters last, and continue the comparison down the string). This is, of course, more or less equivalent to rewriting cmp with your own alphabet. It could undoubtedly be done faster with an iterative solution, but then it could also be done faster in C.

    use strict; use vars '$sortstr'; my @list = qw(a z b y c x); my @list2 = qw(zulu zuzu zucu charlie fred xray yankee bravo alpha); $sortstr = join('', @list); my @sorted_list = sort mycmp @list2; sub mycmp { my ($A, $B)= @_ ? @_ : ($a,$b); my $temp; my $Aspot = ($temp = index($sortstr,substr($A,0,1))) < 0 ? length($sortstr) : $temp; my $Bspot = ($temp = index($sortstr,substr($B,0,1))) < 0 ? length($sortstr) : $temp; return $Aspot <=> $Bspot || mycmp(substr($A,1),substr($B,1)) || $A cmp $B }

    Sorts to:
    alpha zuzu zucu zulu bravo yankee charlie xray fred



    If God had meant us to fly, he would *never* have give us the railroads.
        --Michael Flanders