Syntactic Confectionery Delight PerlMonks

### Re: Sort hash with values

by sundialsvc4 (Abbot)
 on Jun 24, 2013 at 12:52 UTC ( #1040426=note: print w/replies, xml ) Need Help??

in reply to Sort hash with values

I think that I see the problem.   Ordinarily, you would be able to iterate over something like foreach ( sort keys(%IP_store) ) ..., but IP-address strings of varying lengths won’t sort correctly as strings.

The sort verb does allow for a subroutine to be specified, which must return a value that is less than, equal or greater than zero as appropriate, so we do have the mechanism by which to sort the strings the way we want:   as a left-to-right hierarchical collection of four integers.   So, let’s define a separate sub to do this ... something along these (untested) lines:

```
# 'sort' COMPARISON FUNCTION FOR IP-ADDRESSES.
sub ip_compare {
# GRAB THE TWO ARGUMENTS PASSED BY 'SORT'
my (\$a, \$b) = @_;

# SPLIT THE IP-ADDRESSES INTO FOUR =STRINGS= BY
# THE PERIOD CHARACTER.
my (\$a1, \$a2, \$a3, \$a4) = split('\.', @\$a);
my (\$b1, \$b2, \$b3, \$b4) = split('\.', @\$b);

# TYPECAST EACH COMPONENT AS INTEGERS, THEN
# USE INTEGER '<=>' OPERATOR TO COMPARE NUMBERS.
# USE A STACK OF SHORT-CIRCUIT '||' OPS WHICH WILL
# STOP AT (AND RETURN) THE FIRST NON-ZERO RESULT
# IN THE CHAIN.
return
(int(\$a1) <=> int(\$b1))
|| (int(\$a2) <=> int(\$b2))
|| (int(\$a3) <=> int(\$b3))
|| (int(\$a4) <=> int(\$b4));
}

And I would put that subroutine (when debugged), with its comments, into my program.   There are many ways to write it:   this one is reasonably clear.

Now we can do something like sort (ip_compare, keys(%ip_addr)), or something like that, and it should work.   You iterate over the returned list of keys and retrieve the values from the hash by key.

Replies are listed 'Best First'.
Re^2: Sort hash with values
by AnomalousMonk (Chancellor) on Jun 24, 2013 at 17:53 UTC
```# SPLIT THE IP-ADDRESSES INTO FOUR =STRINGS= BY
# THE PERIOD CHARACTER.
my (\$a1, \$a2, \$a3, \$a4) = split('.', @\$a);

The split built-in function does not use single-quotes around a  /PATTERN/ argument to 'meta-quote' the argument: the  '.' in the above really is trying to split on "any character except newline". Use  '\.' to split on a literal period.

```>perl -wMstrict -le
"my \$s = 'a.bb.ccc.d';
;;
my @ra = split '.', \$s;
print 'naked dot';
printf qq{  '\$_'} for @ra;
print '@ra elements: ', scalar @ra;
;;
@ra = split '\.', \$s;
print 'escaped dot';
printf qq{  '\$_'} for @ra;
"
naked dot
@ra elements: 0
escaped dot
'a'  'bb'  'ccc'  'd'

Excellent point.   Thank you.   I have updated the post accordingly.   But, even so, my post consisted of extemporaneous coding.   I did not separately test it to see if it would actually run.   I made it only as an illustration of the essential idea, “implementation left as an exercise to the reader.”

... extemporaneous coding ... “implementation left as an exercise to the reader.”

I understand. But given my perception of the relative inexperience of Rahul Gupta WRT Perl coding, and of the relatively subtle nature of the bug and its manifestation, I wanted to be very explicit about the problen I saw.

I did not separately test it to see if it would actually run.

My own experience with the excellent advice I customarily dispense is that it always works — except when I don't test it, and then, for some reason, it never works! That's why I always try to provide a "complete input-execution-output experience", usually in the form of some kind of command-line capture. That way, there's no question about execution conditions, code, data, etc... Caveat praeceptor.

Create A New User
Node Status?
node history
Node Type: note [id://1040426]
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (3)
As of 2018-03-21 03:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
When I think of a mole I think of:

Results (263 votes). Check out past polls.

Notices?