1: #!/usr/bin/perl -w 2: 3: =head1 by_number 4: 5: This demonstrates the use of a custom sorting routine "by_number" 6: which is designed to sort strings with embedded numbers in the same 7: way that a human might expect, ie taking account of the magnitude of 8: the number rather than the lexicographical ordering of it. 9: 10: This is especially good for sorting IP addresses - ie 11: 12: Input Alpha by_number 13: 10.0.0.2 10.0.0.1 10.0.0.1 14: 10.0.0.1 10.0.0.10 10.0.0.2 15: 10.10.1.1 10.0.0.2 10.0.0.10 16: 10.1.10.1 10.0.1.10 10.0.1.10 17: 10.2.1.2 10.0.2.2 10.0.2.2 18: 10.0.2.2 10.1.10.1 10.1.10.1 19: 10.0.1.10 10.10.1.1 10.2.1.2 20: 10.0.0.10 10.2.1.2 10.10.1.1 21: 22: Try the program for a longer example. 23: 24: =cut 25: 26: use strict; 27: 28: my @list = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [$_, rand] } qw { 29: 1 2 3 4 10 11 12 20 21 22 100 1000 a00 a10 a29 abc1 abc1a abc11b 30: abc111a2 abc1b12 10.0.0.1 10.0.0.2 10.0.0.10 10.0.1.10 10.0.2.2 31: 10.1.10.1 10.2.1.2 10.10.1.1 32: }; 33: 34: my $result = [ 35: [ "Input", @list ], 36: [ "Alpha", sort @list ], 37: [ "by_number", sort by_number @list ], 38: ]; 39: 40: for my $i (0..$#{$result->[0]}) 41: { 42: for my $j (0..$#$result) 43: { 44: printf "%14s", $result->[$j][$i]; 45: } 46: print "\n"; 47: } 48: 49: # Embedded numeric sorter sorts IP addresses & xyz123 50: 51: sub by_number 52: { 53: my @a = split /(\d+)/, $a; 54: my @b = split /(\d+)/, $b; 55: while (@a && @b) 56: { 57: my ($aa, $bb) = (shift(@a), shift(@b)); 58: my $res = ($aa =~ /^\d/ && $bb =~ /^\d/) ? 59: $aa <=> $bb : 60: $aa cmp $bb ; 61: return $res if $res; 62: } 63: return @a <=> @b; 64: } 65: 66: =head2 PS 67: 68: I originally wrote the above split()s as 69: 70: my @a = split /(?<!\d)(?=\d)|(?<=\d)(?!\d)/, $a; 71: 72: Which is is much more exciting being a replacement for \b but for 73: non-number/number boundaries. It is the only time I've ever used 74: all 4 assertions in 1 regexp. However putting brackets in the split 75: is much easier! 76: 77: =head2 PPS 78: 79: There are of course lots of modules on CPAN which do this sort of 80: thing - very similar is Sort::Naturally or Sort::Versions or for the 81: mother of all sorts Sort::ArbBiLex. In production you might like to 82: use one of those - this is merely provided for your entertainment ;-) 83: 84: =cut
|
---|
Replies are listed 'Best First'. | |
---|---|
(tye)Re: Sorting by_number
by tye (Sage) on Sep 15, 2001 at 00:00 UTC | |
by ncw (Friar) on Sep 15, 2001 at 12:04 UTC | |
by tye (Sage) on Sep 15, 2001 at 22:24 UTC |
Back to
Craft