in reply to A new golf challenge - Natural Sorting
This will split the example strings like this:split /(\d+)/
Now the basic trick to do natural sorting, is partwise comparison of the items, comparing the even numbered items (starting at 0) with alphabetical comparison, case insensitive even if you like, and the odd numbered items with numerical comparison.
This is code that does basically that:
sub natcomp { my @a = split /(\d+)/, $a; my @b = split /(\d+)/, $b; my $last = min(scalar @a, scalar @b)-1; my $cmp; for my $i (0 .. $last) { unless($i & 1) { # even $cmp = lc $a[$i] cmp lc $b[$i] || $a[$i] cmp $b[$i] and re +turn $cmp; }else { # odd $cmp = $a[$i] <=> $b[$i] and return $cmp; } } return scalar @a <=> scalar @b; # shortest array comes first }
Let's try this with:
(Note that the DATA section is sorted alphabetically, and that it contains an empty string)chomp(my @array = <DATA>); $\ = "\n"; print for sort natcomp @array; __DATA__ 1 A amstelveen Amsterdam Amsterdam40 Amsterdam40b Amsterdam5 Amsterdamned Chapter 1 Section 10 Chapter 1 Section 3 Chapter 10 Section 2 Chapter 2 Section 1
The result is:
1 A amstelveen Amsterdam Amsterdam5 Amsterdam40 Amsterdam40b Amsterdamned Chapter 1 Section 3 Chapter 1 Section 10 Chapter 2 Section 1 Chapter 10 Section 2
I hope that order is to your liking.
|
|---|