Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Re: Sorting strings

by Hofmator (Curate)
on Aug 30, 2001 at 16:24 UTC ( [id://109052]=note: print w/replies, xml ) Need Help??


in reply to Sorting strings

Well, the cleanest way to go is to use a Schwartzian transform, i.e. a map sort map trick as follows:

my @unsorted = ('-6h0m','+11h39m','+1h7m','-12h8m'); my @sorted = map {$_->[0]} sort {$b->[1] <=> $a->[1]} map { /^([+-])(\d+)h(\d+)m$/; [$_, sprintf("%s%d",$1, $2*60+$3) ] + } @unsorted; print join ', ', @sorted;
As you see, the extraction of hours and minutes can be greatly simplified with a regex.

-- Hofmator

Replies are listed 'Best First'.
Re: Re: Sorting strings
by spartan (Pilgrim) on Aug 30, 2001 at 18:22 UTC
    Hofmator, could you explain (for this novice) what the map portions do in there? I would have to agree with dmmiller2k, very elegant, short, and to the point. Too bad for me I don't get the point though.
    I have one more request, take it easy on me, I write my perl like I wrote my Basic programs 14 years ago.
    TIA.
    -spartan

    Very funny Scotty... Now PLEASE beam down my PANTS!

      I think the for someone who is not very familiar with map, the Schwartzian Transform is a complete mystery. It took me seeing map in action to appreciate its usefulness. So, in the interest of opening a novice's eyes...

      The map function is one of Perl's more wonderous keywords. It's in my list of Perl Milestones of Enlightenment - mysterious at first, powerful yet simple in its action.

      map takes two arguments: an operation of some sort (no pun intended) like a single keyword or a code block (as is used in this case). And a list to operate on. The example given in the pod offers:@chars = map(chr, @nums);. Which takes the list of @nums and performs the chr function on them and assigns the new array to @chars. Or, rewritten with a code block: @chars = map {chr}, @nums; Look right to left, bottom to top, to see the progression. On to the routine...

      So what happens in Hofmator's implementation is every element in the list @unsorted goes through the code block of:

      /^([+-])(\d+)h(\d+)m$/; [$_, sprintf("%s%d",$1,$2*60+$3)]

      The regex splits up the string into +-, hours, and minutes, and the second half creates an anonymous array out of it: first element being the original string, $_, the second being the total minutes of the string.

      Sort does its magic, sorting on the second element (that's 1). No calculation of minutes needed - already done by the map.

      Then the map closest to the @sorted assignment takes the annonymous array, taking just the first element (the original string).

      There's your sorted list of time strings with the minute calculation performed only once per array element.

      HTH

      -Ducky

      Ok, you have read Schwartzian Transform, haven't you? And then I point you to the excellent FMTEYEWTK on sort at CPAN.

      I don't think you will need to - but feel free to get back to me if anything is still unclear after reading that.

      -- Hofmator

        historical sidenote... I believe that the FMTEYEWTK article you mentioned is where the name 'Schwartzian Transform' came from.

        -Blake

Re: Re: Sorting strings
by dmmiller2k (Chaplain) on Aug 30, 2001 at 16:48 UTC

    Nice work. Very clean, elegant.

    As I was reading through the node and its replies, I was formulating just such an approach for my own reply.

    dmm

    Just call me the Anti-Gates ...
    

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2024-04-19 17:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found