Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re: Noodling with natural sorting in perl6

by thundergnat (Deacon)
on Aug 25, 2010 at 18:17 UTC ( [id://857264]=note: print w/replies, xml ) Need Help??


in reply to Noodling with natural sorting in perl6

And now, even more perl sixy...

natural_sort can be rewritten to do no copying and use no intermediate variables. It's kind of obfu but a lot more memory efficient. The » is the hyper operator. It is sort of like map. It means apply that method to each element in the supplied list.

sub natural_sort { return @_ if @_ < 2; my $index = 0; return @_[@_».lc».subst(/(\d+)/, -> $/{ sprintf( "%s%c%s", 0, $0.c +hars, $0) }, :g).map( *~' '~$index++ ).sort.map({@(split(' ',$^_))[*- +1]})]; }

natural_cmp can also use the hyper operator and is now using leg instead of cmp. leg is the string specific comparison operator. (l)ess-(e)qual-(g)reater

sub natural_cmp ($a, $b) { return [leg] ($a, $b)».lc».subst(/(\d+)/, -> $/{ sprintf( "%s%c%s", + 0, $0.chars, $0) }, :g); }

A cached version could look something like below. Note: the cached version actually runs slower than the uncached version right now because of a bug in Rakudo * 2010.07. It evaluates both sides of the //= even if the lhs is defined. :-/ That should be fixed in the near future though. :-)

my %cache; sub cached_natural_cmp ($a, $b) { return [leg] ($a, $b)».lc.map( %cache{ * } //= *.subst(/(\d+)/, -> + $/{ sprintf( "%s%c%s", 0, $0.chars, $0) }, :g)); }

Update: Actually, since perl6 has schwartzian transform semantics built into .sort, this could be very concisely rewritten as:

@array.sort(*.lc.subst(/(\d+)/, -> $/{ sprintf( "%s%c%s", 0, $0.chars +, $0) }, :g));

or, my favorite:

@array.sort: natural(*); sub natural ($) { *.lc.subst(/(\d+)/, -> $/{ sprintf( "%s%c%s", 0, $0. +chars, $0) }, :g) }

used as

.say for %words.keys.sort: natural(*); or %words.keys.sort( natural(*) )».say;

That's just beautiful.

Log In?
Username:
Password:

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

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

    No recent polls found