Perl: the Markov chain saw PerlMonks

### sorting an array

by Selvakumar (Scribe)
 on Jul 10, 2009 at 07:01 UTC Need Help??

Selvakumar has asked for the wisdom of the Perl Monks concerning the following question:

I have a array like this.
@array=("ch1","ch11","ch2","ch5","ch55","ch16");
i need to sort like
ch1
ch2
ch5
ch11
ch16
ch55

How can i do that?

Replies are listed 'Best First'.
Re: sorting an array
by moritz (Cardinal) on Jul 10, 2009 at 07:10 UTC
A reply falls below the community's threshold of quality. You may see it by logging in.
A reply falls below the community's threshold of quality. You may see it by logging in.
Re: sorting an array
by johngg (Canon) on Jul 10, 2009 at 09:50 UTC

A solution using a Schwartzian Transform.

knoppix@Knoppix:~\$ perl -le ' @arr = qw{ ch1 ch11 ch2 ch5 ch55 ch16 }; print for map { \$_->[ 0 ] } sort { \$a->[ 1 ] <=> \$b->[ 1 ] } map { [ \$_, ( split m{(?<=\D)(?=\d)} )[ 1 ] ] } @arr;' ch1 ch2 ch5 ch11 ch16 ch55 knoppix@Knoppix:~\$

I hope this is of interest.

Cheers,

JohnGG

Re: sorting an array
by 1Nf3 (Pilgrim) on Jul 10, 2009 at 07:40 UTC

Sort::Key::Natural seems the best way here, so I'd stick with moritz's suggestion.

But if you want to experiment with sort, it can be done with a custom sort subroutine. An example (tested):

#!/usr/bin/perl -w use strict; sub by_the_number_at_the_end { \$a =~ /(\d+)\$/; my \$end_of_a = \$1; \$b =~ /(\d+)\$/; my \$end_of_b = \$1; return -1 if \$end_of_a < \$end_of_b; return 0 if \$end_of_a == \$end_of_b; return 1 if \$end_of_a > \$end_of_b; } my @array=("ch1","ch11","ch2","ch5","ch55","ch16"); print join ("\n", sort by_the_number_at_the_end @array);

Regards,
Luke

Re: sorting an array
by ELISHEVA (Prior) on Jul 10, 2009 at 08:08 UTC

Sort::Key::Natural will do the trick assuming you can use CPAN (see Yes, even you can use CPAN for tips on how), but there are a couple concepts here that are probably worth learning in any case:

sort lets you define a custom sort routine, like this:
use strict; use warnings; my @aChapters=("ch1","ch11","ch2","ch5","ch55","ch16"); my @aSorted = sort { my (\$sA, \$iA) = (\$a =~ /(^[^\d]+)(\d+)/); my (\$sB, \$iB) = (\$b =~ /(^[^\d]+)(\d+)/); my \$x = \$sA cmp \$sB; (\$x = \$iA <=> \$iB) unless \$x; \$x; } @aChapters; local \$"="\n"; print "@aSorted";

\$a and \$b are special variables that represent the two members of the list you want to sort. The main trick here is to (i) split your name into two parts: an alpha part and a numeric part (ii) compare the alpha part using the alpha comparison operator (cmp) and the numeric part using the numeric comparison operator (<=>). See perlop for more information.

Best, beth

Re: sorting an array
by cdarke (Prior) on Jul 10, 2009 at 10:53 UTC
Given the simple nature of the data, i.e. each element startswith 'ch', I'm surprised others didn't do this:
my @sorted = sort { substr(\$a,2) <=> substr(\$b,2) } @array;
OK, so it's calling substr rather a lot of times, so with a large array that might be slow. Alternatively we could cache it:
@array = map {substr(\$_,2)} @array; my @sorted = sort { \$a <=> \$b } @array; @sorted = map { "ch\$_" } @sorted;
Re: sorting an array
by JavaFan (Canon) on Jul 10, 2009 at 10:59 UTC
map {"ch\$_"} sort {\$a <=> \$b} map {/(\d+)/} @array
should do.
Re: sorting an array
by missingthepoint (Friar) on Jul 10, 2009 at 09:09 UTC
# first num sub num_from_str { my \$str = shift; my (\$num) = \$str =~ /(\d+)/; return \$num; } my @a = qw( ch1 ch11 ch55 ch5 ch2 ch16 ); my @sorted = sort { num_from_str(\$a) <=> num_from_str(\$b) } @a; print "\$_\n" for @sorted;

update: ... but Sort::Key::Natural is a more complete solution, because it sorts based on the alphabetical bits as well.

The zeroeth step in writing a module is to make sure that there isn't already a decent one in CPAN. (-- Pod::Simple::Subclassing)
Re: sorting an array
by pKai (Priest) on Jul 10, 2009 at 11:59 UTC

Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://778819]
Approved by moritz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2022-05-26 11:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
Do you prefer to work remotely?

Results (93 votes). Check out past polls.

Notices?