Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Re: sorting a complex multidimensional hash

by thor (Priest)
on Jul 22, 2004 at 02:37 UTC ( [id://376445]=note: print w/replies, xml ) Need Help??


in reply to sorting a complex multidimensional hash

Doing the naïve thing does the right thing, albeit with warnings:
use warnings; use diagnostics; use strict; my @array = ("8.foo", "6.bar", "7.baz", "5.biz", "3.fizzle", "0.fro", "9.boz"); print join "\n", sort {$a <=> $b} @array; __END__ Argument "8.foo" isn't numeric in sort at 376443.pl line 6 (#1) (W numeric) The indicated string was fed as an argument to an oper +ator that expected a numeric value instead. If you're fortunate the me +ssage will identify which operator was so unfortunate. Argument "6.bar" isn't numeric in sort at 376443.pl line 6 (#1) Argument "7.baz" isn't numeric in sort at 376443.pl line 6 (#1) Argument "5.biz" isn't numeric in sort at 376443.pl line 6 (#1) Argument "3.fizzle" isn't numeric in sort at 376443.pl line 6 (#1) Argument "0.fro" isn't numeric in sort at 376443.pl line 6 (#1) Argument "9.boz" isn't numeric in sort at 376443.pl line 6 (#1) 0.fro 3.fizzle 5.biz 6.baz 7.bar 8.foo 9.boz
However, if you want to dispense with the warnings, you could use the "Schwarzian Transform" like this:
use warnings; use diagnostics; use strict; my @array = ("8.foo", "6.bar", "7.baz", "5.biz", "3.fizzle", "0.fro", "9.boz"); print join "\n", map {$_->[0]} sort {$a->[1] <=> $b->[1]} map { [$_, by_number($_)] } @array; sub by_number { my $value = shift; if ($value =~ m/^(\d+)/) { return $1 } }

thor

Replies are listed 'Best First'.
Re^2: sorting a complex multidimensional hash
by revdiablo (Prior) on Jul 22, 2004 at 06:24 UTC

    There's another option that falls somewhere in the middle or your two examples:

    use warnings; use diagnostics; use strict; my @array = ("8.foo", "6.bar", "7.baz", "5.biz", "3.fizzle", "0.fro", "9.boz"); print join "\n", sort {by_number($a) <=> by_number($b)} @array; sub by_number { my $value = shift; if ($value =~ m/^(\d+)/) { return $1 } }

    Now, of course this is going to be slower than the ST, but whether the optimization is necessary or not depends on a lot of things. Testing on my machine with an array of 70,000 elements, the ST takes 1.6 seconds and this one takes 5. That makes the ST 3.3x faster, but the increase might or might not be worth the more complex code. 5 seconds to sort 70,000 elements is not too shabby, and if the actual data is going to have far fewer, then the extra complexity just might not be worth it.

      That's fair. I suppose I've seen the "map-sort-map" construct enough times that I don't even blink at it. Heck, as long as we're on the subject, I may as well mention the only downfall (that I know) of the ST. As with a lot of things perl, you end up trading memory for speed. For every element in your initial list, you create an anonymous array of two elements. For large* lists, this can actually be prohibitive.

      thor


      For certain values of "large" :)
Re^2: sorting a complex multidimensional hash
by envirodug (Novice) on Jul 22, 2004 at 03:11 UTC
    many thanks (for the code & quick replies)! i think i have the "Schwarzian Transform" example working, i just need to throw a few test cases at it to make sure i'm feeding the correct input through.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (5)
As of 2024-03-28 14:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found