Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re: Save the resultant of " hash sorted by values "

by wind (Priest)
on Mar 23, 2011 at 18:09 UTC ( [id://895068]=note: print w/replies, xml ) Need Help??


in reply to Save the resultant of " hash sorted by values "

As johngg and all others pointed out, %hashes are inherently unsorted so you simply must save an array of keys sorted however you like.

However, your IPs might not be sorted how you want. By using string compare cmp, you're going to end up with the ip 1.0.0.100 coming before 1.0.0.2. Is that what you want? If it isn't, then you simply need to do a Schwartzian Transform

use strict; my %ipaddr = ( a => '192.168.0.1', b => '192.168.0.3', c => '192.168.0.200', d => '192.168.2.1', e => '192.168.100.1', f => '192.168.1.1', ); # The old method: # my @sortedKeys = sort {$ipaddr{$a} cmp $ipaddr{$b}} keys %ipaddr; my @sortedKeys = map {$_->[0]} sort {$a->[1] cmp $b->[1]} map {[$_, join '.', map {sprintf "%03d", $_} split '\.', $ipaddr{$ +_}]} keys %ipaddr; print "$ipaddr{$_}\t$_\n" for @sortedKeys;
Output
192.168.0.1 a 192.168.0.3 b 192.168.0.200 c 192.168.1.1 f 192.168.2.1 d 192.168.100.1 e
Versus the old method of
192.168.0.1 a 192.168.0.200 c 192.168.0.3 b 192.168.1.1 f 192.168.100.1 e 192.168.2.1 d
- Miller

Replies are listed 'Best First'.
Re^2: Save the resultant of " hash sorted by values "
by ikegami (Patriarch) on Mar 23, 2011 at 19:47 UTC

    Is that what you want? If it isn't, then you simply need to do a Schwartzian Transform

    Using the Schwartzian Transform doesn't help at all. It's the generation of a comparable key that made the difference.

    sub ip_to_key { sprintf "%03d", split /\./, $_[0] } my @sortedKeys = sort { ip_to_key($ipaddr{$a}) cmp ip_to_key($ipaddr{$b}) } keys %ipaddr;

    The ST is an optimisation to get more speed out of it. If you really needed speed, this is much faster:

    my @sortedKeys = map substr($_, 4), sort map pack('C4', split(/\./, $ipaddr{$_})) . $_, keys %ipaddr;

      I feel your nitpicking, but fair enough. :) Yes, the point is that he's not sorting on the correct values (most likely) and he can certainly use a function to translate the keys just as well as using a ST. I personally would prefer to keep the code in one place given this is just an example though.

      Also, your function doesn't actually work as is. Fixed:
      sub ip_to_key { join '', map {sprintf "%03d", $_} split /\./, $_[0] }

      Finally, thanks for sharing the pack method of doing a ST as it is definitely snazzier. I use it sometimes as well, but don't feel that it's as immediately decypherable by coders learning about sorts. Although, certainly the easiest method would probably be the functional translation sort {func($a) cmp func($b)}.

        Yes, the point is that he's not sorting on the correct values (most likely) and he can certainly use a function to translate the keys just as well as using a ST.

        No. You must use the function (or equivalent). Whether ST is used or not has no bearing on whether it works or not.

        With STWithout ST
        With functionWorksWorks
        Without functionDoesn't workDoesn't works

        As an aside, using ST doesn't only make the code more complex, I suspect it also makes the makes it slower in this case.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2024-04-24 18:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found