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

shemp has asked for the wisdom of the Perl Monks concerning the following question:

Hi all, i was working on a function to sort ip like strings, and ran into a couple of odd things. Well, here is the sort function - it could be done differently i know, but it shows my situation:
use strict; ... sub ip_sorter {
    my $a_parts = split /\./, $a;
    my $b_parts = split /\./, $b;
my @a_parts = split /\./, $a; my @b_parts = split /\./, $b; my $result; map { return $result if $result = ($a_parts[$_] <=> $b_parts[$_]) +} (0 .. $#a_parts);
so, 1 issue i had was that i couldnt put "no strict" in the map block. I dont know why this is, any insight would be great.

Also, i was unable to find any variable that perl implicitly sets as the result of a comparison. Im thinking something analogous to $! - the value of C errno. So lets just pretend that $^C gets set to the result of the last comparison operation. then i could rewrite my sort with this line:
... map { return $^C if ($a_parts[$_] <=> $b_parts[$_]) }; ...
I've looked for this variable at search.cpan.org/author/JHI/perl-5.8.0/pod/perlvar.pod to no avail.

Fixed typo at author's req - dvergin 2003-05-14

Replies are listed 'Best First'.
Re: Comparison result capture???
by pzbagel (Chaplain) on May 14, 2003 at 17:20 UTC

    I know that you are looking at this from another perspective but if you are indeed sorting IPs, converting them to a numerical equivalent from dotted decimal and then sorting them numerically is a slick way to go.

    I didn't write it, but here is a post from dws on IP sorting. It uses pack to convert the IPs and then a sweet Orcish Maneuver to speed up the sort.

    HTH

Re: Comparison result capture???
by chip (Curate) on May 14, 2003 at 16:22 UTC
    You're assigning the split results to scalars but not using those scalars in the map block, which seems a bit, well, odd. What's up with that?

    As for the "last result" idea, foreach (which is spelled "for" by all good monks) will often serve the purpose of avoiding duplicate expressions:

    $_ and return $_ for $a_parts[$_] <=> $b_parts[$_];

    I've also run into odd restrictions on no strict and I really wish I understood what was broken by accident and what on purpose WRT that.

    Finally, I'll take off a fractional style point for using a map block where you really meant foreach....

        -- Chip Salzenberg, Free-Floating Agent of Chaos

      speaking of odd, your use of for for a 1 element array is pretty novel all in its own right.
        I wish I could say I'd invented that, but I stole it from Tom C. I don't know whether he stole it in turn....

            -- Chip Salzenberg, Free-Floating Agent of Chaos

      Didn't you mean
      my $x; ($x = $a_parts[$_] <=> $b_parts[$_]) && return $x for 0 .. $#a_parts;
      You're using $_ too many times.

      ------
      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

      Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

        I'll grant you that my code uses $_ with more than one meaning, and some people may not like that. But it's clear enough to me. Seems to work, too.

            -- Chip Salzenberg, Free-Floating Agent of Chaos

      Oops! I meant to split $a and $b into @a_parts and @b_parts, which makes a lot more sense. I have submitted a change request to the editors.
Re: Comparison result capture???
by flounder99 (Friar) on May 14, 2003 at 19:57 UTC
    You can always sort IPs like this
    use strict; my @ips = ( "1.2.3.4", "1.2.3.5", "1.2.3.3", "2.2.3.4", "1.0.2.3"); @ips = map {$_->[1]} sort {$a->[0] cmp $b->[0]} map { [ join(".", map {sprintf "%03d", $_} split('\.', $_) ), $_ ] } @ips; print join "\n", @ips; __OUTPUT__ 1.0.2.3 1.2.3.3 1.2.3.4 1.2.3.5 2.2.3.4

    --

    flounder