package Sort::Key::Natural;
our $VERSION = '0.03';
require Exporter;
our @ISA = qw( Exporter );
our @EXPORT_OK = qw( natkeysort
natkeysort_inplace
rnatkeysort
rnatkeysort_inplace
mkkey_natural
natsort
rnatsort
natsort_inplace
rnatsort_inplace );
sub mkkey_natural {
my $nat = @_ ? shift : $_;
my @parts = $nat =~ /\d+|[[:alpha:]]+/g;
for (@parts) {
if (/^\d/) {
s/^0+//;
my $len = length;
my $nines = int ($len / 9);
my $rest = $len - 9 * $nines;
$_ = ('9' x $nines) . $rest . $_;
}
}
return join("\0", @parts);
}
use Sort::Key::Register natural => \&mkkey_natural, 'string';
use Sort::Key::Register nat => \&mkkey_natural, 'string';
use Sort::Key::Maker natkeysort => 'nat';
use Sort::Key::Maker rnatkeysort => '-nat';
use Sort::Key::Maker natsort => \&mkkey_natural, 'str';
use Sort::Key::Maker rnatsort => \&mkkey_natural, '-str';
1;
=head1 NAME
Sort::Key::Natural - fast natural sorting
=head1 SYNOPSIS
use Sort::Key::Natural qw(natsort);
my @data = qw(foo1 foo23 foo6 bar12 bar1
foo bar2 bar-45 foomatic b-a-r-45);
my @sorted = natsort @data;
print "@sorted\n";
# prints:
# b-a-r-45 bar1 bar2 bar12 bar-45 foo foo1 foo6 foo23 foomatic
use Sort::Key::Natural qw(natkeysort);
my @objects = (...);
my @sorted = natkeysort { $_->get_id } @objects;
=head1 DESCRIPTION
This module extends the L<Sort::Key> family of modules to support
natural sorting.
Under natural sorting, strings are splitted at word and number
boundaries, and the resulting substrings are compared as follows:
=over 4
=item *
numeric substrings are compared numerically
=item *
alphabetic substrings are compared lexically
=item *
numeric substrings come always before alphabetic substrings
=back
Spaces, symbols and non-printable characters are only considered for
splitting the string into its parts but not for sorting. For instance
C<foo-bar-42> is broken in three substrings C<foo>, C<bar> and C<42>
and after that the dashes are ignored.
Also, once this module is loaded, the new type C<natural> (or C<nat>) will
be available from L<Sort::Key::Maker>. For instance:
use Sort::Key::Natural;
use Sort::Key::Maker i_rnat_keysort => qw(integer -natural);
creates a multikey sorter C<i_rnat_keysort> accepting two keys, the
first to be compared as an integer and the second in natural
descending order.
=head2 FUNCTIONS
the functions that can be imported from this module are:
=over 4
=item natsort @data
returns the elements of C<@data> sorted in natural order.
=item rnatsort @data
returns the elements of C<@data> sorted in natural descending order.
=item natkeysort { CALC_KEY($_) } @data
returns the elements on C<@array> naturally sorted by the keys
resulting from applying them C<CALC_KEY>.
=item rnatkeysort { CALC_KEY($_) } @data
is similar to C<natkeysort> but sorts the elements in descending
order.
=item natsort_inplace @data
=item rnatsort_inplace @data
=item natkeysort_inplace { CALC_KEY($_) } @data
=item rnatkeysort_inplace { CALC_KEY($_) } @data
these functions are similar respectively to C<natsort>, C<rnatsort>,
C<natsortkey> and C<rnatsortkey>, but they sort the array C<@data> in
place.
=item mkkey_natural $key
transforms key C<$key> in a way that when sorted with L<Sort::Key>
keysort results in a natural sort. If the argument C<$key> is not
provided it defaults to C<$_>
=back
=head1 SEE ALSO
L<Sort::Key>, L<Sort::Key::Maker>.
Other module providing similar functionality is L<Sort::Naturally>.
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2006 by Salvador FandiE<ntilde>o,
E<lt>sfandino@yahoo.comE<gt>.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.4 or,
at your option, any later version of Perl 5 you may have available.
=cut