0

I have an array with elements

@a =(mem_64x128,mem_8x64,mem_8x128,mem_128x64);

I want the array to be sorted in the following manner

   mem_8x64,mem_8x128,mem_64x128,mem_128x64

But when I sort @a, the output I get is

mem_128x64
mem_64x128
mem_8x64
mem_8x128

Can anyone please help. Thanks

3
  • 1
    It is because when sorting alphabetically 128 comes before 64. You might be interested in this: stackoverflow.com/q/19544253/725418 Commented Oct 25, 2013 at 10:15
  • But how can I do this for an array? Commented Oct 25, 2013 at 10:29
  • The same way. You sort a list of elements, not a data structure. Commented Oct 25, 2013 at 11:15

5 Answers 5

4

Use custom comparing function sort (perldoc):

sort {
   my ($c,$d) = $a =~ /(\d+)x(\d+)/;
   my ($e,$f) = $b =~ /(\d+)x(\d+)/;
   $c<=>$e || $d<=>$f;
} @a;

or faster one:

my %h;
@a = sort  {
   $h{$a} || ( @{$h{$a}} = $a =~ /(\d+)x(\d+)/ );
   $h{$b} || ( @{$h{$b}} = $b =~ /(\d+)x(\d+)/ );
   $h{$a}->[0] <=> $h{$b}->[0] || $h{$a}->[1] <=> $h{$b}->[1];
} @a;
Sign up to request clarification or add additional context in comments.

Comments

3

Try something like this:

#!/usr/bin/perl
use strict;
use warnings;

my @a =("mem_64x128","mem_8x64","mem_8x128","mem_128x64");

print sort byFirst sort bySecond @a;

sub byFirst{
# Extract first number from a
my $y=$a;
$y =~ s/.*_//;
$y =~ s/x.*//;

# Extract first number from b
my $z=$b;
$z =~ s/.*_//;
$z =~ s/x.*//;
return $y <=> $z;
}

sub bySecond{
# Extract second number from a
my $y=$a;
$y =~ s/.*x//;

# Extract second number from b
my $z=$b;
$z =~ s/.*x//;
return $y <=> $z;
}

Comments

2

This is another use case where the nsort function from the CPAN module Sort::Naturally works as humans expect it:

@a =(mem_64x128,mem_8x64,mem_8x128,mem_128x64); # no strict!
use Sort::Naturally qw(nsort);
print join(',', nsort @a), "\n";

Output is:

mem_8x64,mem_8x128,mem_64x128,mem_128x64

Comments

2

Here is one way to do it.

use warnings;
use strict;


my @a = ('mem_64x128', 'mem_8x64', 'mem_8x128', 'mem_128x64');

my @sorted_a = sort { (split /[_x]/, $a)[1] <=> (split /[_x]/, $b)[1]
                           or
          (split /[_x]/, $a)[2] <=> (split /[_x]/, $b)[2]
} @a;

print "$_\n" foreach @sorted_a;

OUTPUT

mem_8x64
mem_8x128
mem_64x128
mem_128x64

2 Comments

/_|x/ is better written /[_x]/.
@TLP Thanks for the observation. I fixed it.
1

Elements are sorted by first, and second number in ascending order,

my @r = qw(mem_64x128 mem_8x64 mem_8x128 mem_128x64);

@r = map { $_->[0] }
  sort {
    $a->[1] <=> $b->[1] || $a->[2] <=> $b->[2]
  }
  map { [$_, /(\d+)/g ] } @r;

print "@r\n";

output

mem_8x64 mem_8x128 mem_64x128 mem_128x64

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.