http://qs321.pair.com?node_id=970881


in reply to Sorting Hash / Array

Not sure which part you are puzzling over. Simplistically:
use strict; use warnings; my $VAR1; $VAR1 = { '127' => { 'network' => '10.182.48.0/24', 'VLAN' => '3509' }, '32' => { 'network' => '10.182.12.0/25', 'VLAN' => '2121' }, '90' => { 'network' => '10.183.243.128/25', 'VLAN' => '3494' } }; sub custom { # $a and $b are keys my $anet = $VAR1->{$a}{network}; my $bnet = $VAR1->{$b}{network}; return $anet cmp $bnet; } my @result = sort custom keys %$VAR1;
However it would probably be better to use Net::IPAddress to convert the IP address to a 32-bit int, then use <=> to compare them, and compare the ports if the addresses are the same.

Replies are listed 'Best First'.
Re^2: Sorting Hash / Array
by sauoq (Abbot) on May 16, 2012 at 18:23 UTC

    I'd rather see that sort routine inlined in this case. As it stands, nasty subtle bugs can creep in with some sloppy maintenance. Say at some point someone has to add $VAR2 and perform similar sorting on it... and make the all too simple mistake of thinking they can add a line that reads:

    my @result2 = sort custom keys %$VAR2;
    Oops. And that's just one example.

    This is perfectly readable:

    my @result = sort { $VAR1->{$a}{network} cmp $VAR1->{$b}{network} } keys %$VAR1;

    If it was something you had to do repeatedly, it would be better to wrap the whole sort in a sub...

    sub keys_sorted_by_network { my $h = shift; sort { $h->{$a}{network} cmp $h->{$b}{network} } keys %$h; } my @result = keys_sorted_by_network($VAR1);
    -sauoq
    "My two cents aren't worth a dime.";
      Accepted, but...
      the string comparison is not accurate for IP addresses. Originally I was going to do a cascade comparison on each octet, but lost the will to live and suggested Net::IPAddress instead. Inline code can be messy, but I accept your argument about the hard-coded reference.
        the string comparison is not accurate for IP addresses. Originally I was going to do a cascade comparison on each octet, but lost the will to live and suggested Net::IPAddress instead.

        I know. I didn't say anything because A) your suggestion to use Net::IPAddress was better than what I was going to suggest:

        unpack "N", pack "C*", split /\./, $ip_address;
        and B) I was heading out the door. :-)

        -sauoq
        "My two cents aren't worth a dime.";