in reply to How to perform different sorts on multiple sections of items in the same array

Very-elaborate sorting requirements such as these can be satisfied by creating an appropriate function for use with the sort verb.   As you know, this function must return a value that is either less-than, equal-to, or greater-than zero, based on its comparison of two strings ($a and $b) that are presented to it.   Typically, this is an “in-line” function such as { $a <=> $b } (using an operator that is expressly designed for this purpose), but it does not have to be.   You can write an entirely separate sub and refer to it within the sort verb, and this is what I suggest that you do.

Let me describe my notion just in words.   This is what the sub will do, each time it is called.

  1. First, classify the two strings into “groups.”
    1. Group #1 consists of those which contain an “r.”
    2. Group #2 consists of those characters which start with “e.”
    3. Group #3 consists of those strings which do not fall into either of the other two groups.
  2. If the group-number of the two strings is unequal, return the difference between the two group-numbers.   (Only the sign of the result matters.)   This will cause the groups to be separated:   the groups will occur in the final output in order of group-number, and, within their respective groups, they will be sorted as (see below) each group requires.
  3. Otherwise (the group-number is the same ...), return a value that is appropriate for each group.
    1. Group #1 can simply use <=>.
    2. Group #2 can (probably) remove the first characters, then use that operator, or use it on a substring.   (You probably need to consider more than just the one character.   Otherwise, multiple strings with the same fourth-character would have an unpredictable result-order, since differing strings would all be seen as “equal.”)
    3. The third, to achieve a reverse-sort, would apply the <=> operator with the two operands reversed.

Notice that you are not splitting the array and sorting each piece.   You are not using memory-hungry exotica like Schwartz.   This notion can be applied to sorts of any size, and it applies equally well to both in-memory and disk-based sorts.

Q.E.D.

Replies are listed 'Best First'.
Re^2: How to perform different sorts on multiple sections of items in the same array
by Anonymous Monk on Dec 29, 2014 at 12:49 UTC
    Group #1 can simply use <=>

    If you're going to describe someone else's solution without giving credit, at least get it right. <=> does numeric comparison.

Re^2: How to perform different sorts on multiple sections of items in the same array
by karlgoethebier (Abbot) on Dec 29, 2014 at 13:04 UTC
Re^2: How to perform different sorts on multiple sections of items in the same array
by Anonymous Monk on Dec 29, 2014 at 19:01 UTC
    You probably need to consider more than just the one character. Otherwise, multiple strings with the same fourth-character would have an unpredictable result-order, since differing strings would all be seen as “equal.”
    You have to upgrade your Perl!

    sort

    In 5.7, the quicksort implementation was replaced with a stable mergesort algorithm
Re^2: How to perform different sorts on multiple sections of items in the same array
by Laurent_R (Canon) on Dec 29, 2014 at 19:52 UTC
    You are not using memory-hungry exotica like Schwartz.
    It is precisely when the comparison routine is complicated and likely to be time-expensive that the Schwartzian transform gives the best performance improvement.

      The statement about <=> vs. the string version, cmp, is of course my blunder.   Oops.

      The idea itself is certainly not new:   that’s how they did it (and, still do it ...) in the earliest COBOL days.   But it most certainly isn’t “plagarism,” as if such a curious term could actually apply in this context ... which it obviously can’t.   (In general, several of you routinely step over the line of decorum and civility . . . and I’ve simply given up asking you to stop.   But, I digress.)

      A lot depends on exactly how much data we might be dealing with.   If the whole shebang fits easily within available memory, then it matters very little how you do it:   split the in-memory list into three in-memory lists, sort each one, splice ’em all together into one, and you’re done.   Or, pay your nod to Mr. Schwartz, if you prefer.   No discussion required.   But, if data volumes are large ... especially if they are very large ... custom sort-comparison routines work extremely well.

      I decided to make this suggestion ... not to hear myself babble, nor with the slightest concern for “votes” ... but to offer an alternative strategy.   “There’s more than one way to do it,™” and here’s another.   Yes, it involves a non-trivial subroutine.   But, so do many sorts.   Even if it is deemed not-useful in this particular (small?) case, it is a useful alternative to keep in mind.