Wow, I feel like the ultimate necroposter here.
I stumbled across this solution, and found it fell over when it met the likes of the following:
$A <=> $B does a numerical comparison, but strips any leading zeroes from the number, so how 1.02 and 1.2 are sorted will depend on their original order in the list - Tcl's dictionary sort doesn't seem to do this, and will place 1.2 above 1.02 in the sort.qw{ 1.01 1.3 1.02 1.2 }
So I extended your example to check for the string length of the compared numbers if they match numerically - If they match numerically, but have differing string lengths, then one must have leading zeroes. I also implemented the code into a subroutine:
sub dict_sort { my @unsorted = @_; my @sorted = map $_->[0], sort { my $i = 0; { my $A = $a->[1][$i]; my $B = $b->[1][$i]; defined($A) || defined($B) # Stop if both undef and ( defined($A) <=> defined($B) # Defined wins over undef or ( $A !~ /\d/ || $B !~ /\d/ # $A or $B is non-integer ? (lc $A cmp lc $B) # ?? Stringy lowercase || ( $A cmp $B) # -> Tie breaker : $A <=> $B # :: $A and $B are integers or ( length($A) <=> length($B) # If numeric comparison ret +urns the same, check length to sort by leading zeroes ) ) or ++$i && redo # tie => next part ); } } map [ $_, [ split /(\d+)/ ] ], @unsorted; return @sorted; }
I'm not sure that this thread will ever get any more posts, but hopefully this helps somebody out!
In reply to Re^2: Dictionary-style sort a la Tcl?
by Rohaq
in thread Dictionary-style sort a la Tcl?
by argathin
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |