There's more than one way to do things PerlMonks

### How do I do a natural sort on an array?

 on Mar 30, 2001 at 00:46 UTC Need Help??
Contributed by Anonymous Monk on Mar 30, 2001 at 00:46 UTC
Q&A  > sorting

#### Description:

How do I do a natural sort on an array? i.e. each array element is contains a string made up of numbers and letters.

 Answer: How do I do a natural sort on an array?contributed by tye ```my @sorted= grep {s/(^|\D)0+(\d)/\$1\$2/g,1} sort grep {s/(\d+)/sprintf"%06.6d",\$1/ge,1} @data; [download]``` See RE: RE: Re: Sorting on Section Numbers some important style comments. Features and limitations: Strips extra leading zeros from digit strings Doesn't handle floating point numbers at all well Sorts negative integers in reverse after positive integers Uses very little extra memory You must specify the maximum number of digits your integers will have (6 in the above code) Answer: How do I do a natural sort on an array?contributed by tye ```my %data; foreach my \$data ( @data ) { ( my \$sort= \$data ) =~ s/(0*)(\d+)/ pack("C",length(\$2)) . \$1 . \$2 /ge; \$data{\$sort}= \$data; } my @sorted= @data{ sort keys %data }; [download]``` Bugs and features Doesn't properly sort decimal values like 12.34 Sorts negative integers in reverse after positive integers Requires more memory than other methods I'll be adding Answer: How do I do a natural sort on an array?contributed by indigo @a = sort @b; will sort lexigraphically. @a = sort { \$a <=> \$b } @b; will sort numerically. @a = sort &naturally @b; will sort "naturally", where naturally() is a compare routine of your own devising. perldoc -f sort for more info. Answer: How do I do a natural sort on an array?contributed by Dominus I'm not exactly sure what you want (it would have helped if you had provided an example) but here's what I use: ```sub byfile { my @a = split /(\d+)/, \$a; my @b = split /(\d+)/, \$b; my \$M = @a > @b ? @a : @b; my \$res = 0; for (my \$i = 0; \$i < \$M; \$i++) { return -1 if ! defined \$a[\$i]; return 1 if ! defined \$b[\$i]; if (\$a[\$i] =~ /\d/) { \$res = \$a[\$i] <=> \$b[\$i]; } else { \$res = \$a[\$i] cmp \$b[\$i]; } last if \$res; } \$res; } [download]``` This may be more complicated than you need. Given the following: ```53 7 119 53red red5 red6 red7 red67 red6.jpg red12.jpg green4.jpg blue2.jpg blue1000.jpg blue2.jpg58 [download]``` it produces the following output: ```7 53 53red 119 blue2.jpg blue2.jpg58 blue1000.jpg green4.jpg red5 red6 red6.jpg red7 red12.jpg red67 [download]``` Lucs St. Louis also suggests: ``` while (defined (my \$A = shift @a) and defined (my \$B = shift @b)) { \$res = (\$A =~ /\d/) ? \$A <=> \$B : \$A cmp \$B; return \$res if \$res; } return defined \$A ? -1 : 1; [download]``` Hope this helps. Answer: How do I do a natural sort on an array?contributed by salva Sort::Key::Natural is fast, can handle numbers of unlimited size and doesn't have problems with unicode: ```use Sort::Key::Natural qw(natsort); my @sorted = natsort @data; [download]``` Answer: How do I do a natural sort on an array?contributed by ihb You can use Sort::Naturally. Answer: How do I do a natural sort on an array?contributed by Jammerwoch I wrote the following before finding the delightful Sort::Naturally library function. I reccommend using that over what I've done, but maybe people are curious how it might be done. Or maybe someone needs to fine-tune or customize it. The following code is NOT efficient. In particular, the calling of naturalSortInner with \$a and \$b as arguments completely eliminates the efficiency of having \$a and \$b. However, it was necessary for the recursive nature of naturalSortInner. ```#!/usr/bin/perl sub naturalSortInner { \$x = uc( shift ); \$y = uc( shift ); if( !(\$x =~ /\d+(\.\d+)?/) ) { return \$x cmp \$y; } \$xBefore = \$`; \$xMatch = \$&; \$xAfter = \$'; if( !(\$y =~ /\d+(\.\d+)?/) ) { return \$x cmp \$y; } if( \$xBefore eq \$` ) { if( \$xMatch == \$& ) { return naturalSortInner( \$xAfter, \$' ); } else { return \$xMatch <=> \$&; } } else { return \$x cmp \$y; } print "\n\ +n"; } sub naturalSort { naturalSortInner( \$a, \$b ); } @arr = ( 'beta', 'Alpha', 'Gamma1', 'Gamma', '23', '5', 'Version1', 'Version1.1', 'Version1.2', 'Version11.1-Sub1', 'Version11.1-Sub10', 'Version11.1-Sub3', 'x23sub5', 'Version2', 'Version2.1', 'GammaGlobulin', 'Gamma10', 'c', 'Gamma2', 'Gamma3', ); print join( "\n", sort naturalSort @arr ) . "\n"; [download]```

• Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
• Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
• Read Where should I post X? if you're not absolutely sure you're posting in the right place.
• Posts may use any of the Perl Monks Approved HTML tags:
a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
• You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
 For: Use: & & < < > > [ [ ] ]
• Link using PerlMonks shortcuts! What shortcuts can I use for linking?

Create A New User
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (1)
As of 2018-01-21 10:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
How did you see in the new year?

Results (227 votes). Check out past polls.

Notices?