Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

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

by johngg (Canon)
on Dec 30, 2014 at 01:03 UTC ( [id://1111659]=note: print w/replies, xml ) Need Help??


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

Rather than complicated sorting routines, perhaps it would be preferable to set up a couple of "flags" depending on what type the string is and, consequently, what character to sort on then pack them along with the original string to do a GRT sort. This will not be stable for the last two categories if the strings share the same sorting character, at which point they will be sorted in ascending alpha.

use strict; use warnings; use 5.014; my @strings = qw{ cabin prawn pail error reptile engine copy echo soap eskimo carpet emblem skunk }; say for map { substr $_, 8 } sort map { my( $type, $ord ); if ( m{r} ) { $type = 0; $ord = 0; } elsif ( m{^e} ) { $type = 1; $ord = ord substr $_, 2, 1; } else { $type = 2; $ord = 255 - ord substr $_, -1, 1; } pack q{NNa*}, $type, $ord, $_; } @strings;

The output.

carpet error prawn reptile emblem engine echo eskimo copy soap cabin pail skunk

I hope this is of interest.

Update: Corrected statement re. stable sorting, s/first/last/

Cheers,

JohnGG

Replies are listed 'Best First'.
Re^2: How to perform different sorts on multiple sections of items in the same array
by BrowserUk (Patriarch) on Dec 30, 2014 at 02:00 UTC

    For your sample data, the OPs specifications, should lead to an ordering of:

    copy carpet soap error prawn emblem cabin echo pail engine reptile esk +imo skunk

    Not:

    carpet error prawn reptile emblem engine echo eskimo copy soap cabin p +ail skunk

    Consider the OPs 3-part specification and the following:

    orig pre-r sort-r pre-e sort-e pre-o sort-O + final cabin cabin copy + copy prawn prawn carpet + carpet pail pail soap + soap error error error + error reptile reptile prawn + prawn engine engine emblem + emblem copy copy cabin + cabin echo echo echo + echo soap soap pail + pail eskimo eskimo engine + engine carpet carpet reptile + reptile emblem emblem eskimo + eskimo skunk skunk skunk + skunk

    The problem with your algorithm is, that is doesn't exclude those items that match the first criteria, from being considered by the second criteria, if the also match it; but the OPs specifications (emphasis added):

    all the strings inside the array that contain an “r” and sort those in ascending alphabetical order. For the elements that are left, find the ones that start with an “e” and sort those by ascii value of their third character. And for the ones that are left reverse sort by their last letter alphabetically.

    Your algorithm does not exclude items that contain an 'r' from being considered when processing items that start with an 'e'. Eg. 'error'.

    Nor does it exclude items that contain an 'r', or start with an 'e', from being processed when reverse sorting "the ones that are left".


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Perhaps I misinterpreted the OP's spec. I thought the requirement was to sort all those containing an 'r' followed by those starting with an 'e' and finally the remainder but I can see that your interpretation of leaving each set in their relative positions could be more accurate. Perhaps estreb could clarify?

      Your algorithm does not exclude items that contain an 'r' from being considered when processing items that start with an 'e'. Eg. 'error'.

      Nor does it exclude items that contain an 'r', or start with an 'e', from being processed when reverse sorting "the ones that are left".

      I'm not sure you are correct in those statements. The if ( m{r} ) { ... } elsif ( m{^e} ) { ... } else { ... } section assigns ascending values to $type which is packed as the first term and becomes the primary key for the sort. Thus all those starting with an 'r' are sorted separately from those starting with 'e' which are again separate from the remainder. I think this is demonstrated by the output.

      carpet } error } Strings containing an 'r' anywhere prawn } are sorted ascending alpha reptile } emblem } engine } Strings starting with 'e' but not echo } containing an 'r' are sorted ascending eskimo } alpha on the third character copy } soap } Strings neither containing an 'r' nor cabin } starting with 'e' are sorted descending pail } alpha on the last character skunk }

      Please let me know if you still think I am having a senior moment and have got this aspect of the algorithm completely wrong.

      Update: Corrected wrong variable in explanation, s/$ord/$type/

      Cheers,

      JohnGG

        Please let me know if you still think I am having a senior moment and have got this aspect of the algorithm completely wrong.

        No. I was :)

        Looking again at your code, post reading your explanation, I now see the effect/purpose of your $type variable -- to effectively segregate and pre-order the three subsets of the data.

        And, looking again at the OPs description, yours is just as valid an interpretation of it, as mine.

        Sorry for having misinterpreted your code the first time; and thankyou for the patient explanation. I learnt something -- which is always nice :)


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re^2: How to perform different sorts on multiple sections of items in the same array
by johngg (Canon) on Dec 31, 2014 at 00:40 UTC

    To add stable sorting for the last two categories, restrict the sort to $type and $ord (packed as NN so taking 8 bytes) unless the $type is 0 for both terms, in which case sort the entire strings.

    use strict; use warnings; use 5.014; my @strings = qw{ cabin prawn eminent pail error reptile engine copy echo soap eskimo carpet elias emblem skunk cheap }; say for map { substr $_, 8 } sort { unpack( q{N}, $a ) || unpack( q{N}, $b ) ? substr( $a, 0, 8 ) cmp substr( $b, 0, 8 ) : $a cmp $b; } map { my( $type, $ord ); if ( m{r} ) { $type = 0; $ord = 0; } elsif ( m{^e} ) { $type = 1; $ord = ord substr $_, 2, 1; } else { $type = 2; $ord = 255 - ord substr $_, -1, 1; } pack q{NNa*}, $type, $ord, $_; } @strings;

    The output, note that 'eminent' and 'elias' have the same 3rd character but now retain their relative order, as do 'soap' and 'cheap' with matching final characters in the last category.

    carpet error prawn reptile emblem engine echo eminent elias eskimo copy soap cheap cabin pail skunk

    I hope this is of interest.

    Cheers,

    JohnGG

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1111659]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (7)
As of 2024-04-24 11:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found