in reply to Re: Sorting a hash of IP addresses?
in thread Sorting a hash of IP addresses?

may I add that a Schwartzian Transform might help speeding up the sort. Then the split doesn't have to be done over and over again. This leads to

my @sorted_keys = map {$_->[0]} sort {$a->[1] <=> $b->[1] || $a->[2] <=> $b->[2] || $a->[3] <=> $b->[3] || $a->[4] <=> $b->[4]} map { [ $_, split /\./ ] } keys %ip; foreach (@sorted_keys) { # do something }

Instead of splitting one could also use the MZSanford's suggestion and sort on a zeropadded string in the transformation.

Update:
The code above was written to resemble as closely as possible davorg's original subroutine. For better solutions (in terms of performance) see blakem's and davorg's responses to my post.

-- Hofmator

Replies are listed 'Best First'.
Re: Re: Re: Sorting a hash of IP addresses?
by blakem (Monsignor) on Dec 05, 2001 at 16:21 UTC
    You could simplify the comparison by upgrading your transformation. Instead of just splitting it into four pieces, why not convert it to dotless notation (i.e. the decimal representation of the underlying 32 bits). Comparing ips in dotless notation is trivial... a single <=> is all you need.

    In general it makes sense to push the complexity into the transformation since it is only done once for each element in the list.

    Something like: (warning untested)

    my @sorted_keys = map {$_->[0]} sort {$a->[1] <=> $b->[1]} map { [ $_, unpack("N",pack("C4",split(/\./,$_))) ] + } keys %ip;
    * I borrowed the ip => dotless conversion from Fletch's golf entry

    -Blake

      And let's not forget that sorting IP addresses was the canonical example of the packed default sort that Uri Guttman and Larry Rosler used in their most excellent paper on Perl sorting. Changing their code a little gives us this:

      @sorted_keys = map substr($_, 4) => sort map pack('C4' => /(\d+)\.(\d+)\.(\d+)\.(\d+)/) . $_ => keys %ip;
      --
      <http://www.dave.org.uk>

      "The first rule of Perl club is you do not talk about Perl club."
      -- Chip Salzenberg