Sam B
Sam B

Reputation: 27608

Perl sorting Alpha characters in a special way

I know this question may have been asked a million times but I am stumped. I have an array that I am trying to sort. The results I want to get are

A
B
Z
AA
BB

The sort routines that are available dont sort it this way. I am not sure if it can be done. Here's is my perl script and the sorting that I am doing. What am I missing?

# header
use warnings;
use strict;
use Sort::Versions;
use Sort::Naturally 'nsort';

print "Perl Starting ... \n\n"; 

my @testArray = ("Z", "A", "AA", "B", "AB");

#sort1
my @sortedArray1 = sort @testArray;
print "\nMethod1\n";
print join("\n",@sortedArray1),"\n";


my @sortedArray2 = nsort @testArray;
print "\nMethod2\n";
print join("\n",@sortedArray2),"\n";


my @sortedArray3 = sort { versioncmp($a,$b) }  @testArray;
print "\nMethod3\n";
print join("\n",@sortedArray3),"\n";


print "\nPerl End ... \n\n"; 

1;

OUTPUT:

Perl Starting ...


Method1
A
AA
AB
B
Z

Method2
A
AA
AB
B
Z

Method3
A
AA
AB
B
Z

Perl End ...

Upvotes: 6

Views: 279

Answers (2)

ikegami
ikegami

Reputation: 386206

my @sorted =
   sort {
      length($a) <=> length($b)
         ||
      $a cmp $b
   }
      @unsorted;

or

# Strings must be have no characters above 255, and
# they must be shorter than 2^32 characters long.
my @sorted = 
   map substr($_, 4),
      sort
         map pack("N/a*", $_),
            @unsorted;

or

use Sort::Key::Maker sort_by_length => sub { length($_), $_ }, qw( int str );

my @sorted = sort_by_length @unsorted;

The second is the most complicated, but it should be the fastest. The last one should be faster than the first.

Upvotes: 4

Tanktalus
Tanktalus

Reputation: 22284

I think what you want is to sort by length and then by ordinal. This is easily managed with:

my @sortedArray = sort {
    length $a <=> length $b ||
    $a cmp $b
} @testArray;

That is exactly as the English: sort based on length of a vs b, then by a compared to b.

Upvotes: 7

Related Questions