1

I have an array which looks like this:

array[0]: 6 8
array[1]: 12 9 6
array[2]: 33 32 5
array[3]: 8 6

I want to sort this array so that it looks like this:

array[0]: 6 8
array[1]: 6 9 12
array[2]: 5 32 33
array[3]: 6 8

I know I can sort the array with @newarray = sort {$a cmp $b} @array;, but I need to sort the elements in each line as well. How can I do that?

1
  • 3
    is that an array of arrays or are they strings? Commented Jul 19, 2010 at 10:06

3 Answers 3

8

Update 2021-03-16: Dear future visitors, I have the accepted answer, and I'm still getting upvotes, but @FMc's solution is clearly better than mine. (FMc and dalton have the same answer, but as far as I can tell, FMc got there first.)

In any case, if you have a situation like this use Perl's built-in map rather than my original answer of a custom subroutine.

Original answer: Assuming that you have an array of strings there, and that all you want is to sort each string as if it were a sub-array of numbers (but leave it a string?):

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

my @array = ('6 8', '12 9 6', '33 32 5', '8 6');

foreach my $string (@array) {
    $string = split_sort($string);
}

sub split_sort {
    my $string = shift @_;
    my @internal_nums = split ' ', $string;
    @internal_nums = sort {$a <=> $b} @internal_nums;
    return join ' ', @internal_nums;
}

print "@array\n";
Sign up to request clarification or add additional context in comments.

Comments

7

You could also solve it using map:

#!/usr/bin/env perl

my @numbers = (
    '6 8',
    '12 9 6',
    '33 32 5',
    '8 6',
);

my @sorted;
push (@sorted, map { join " ", sort { $a <=> $b }  (split / /, $_) } @numbers);


print "$_\n" for @sorted;

Outputs:

6 8
6 9 12
5 32 33
6 8

4 Comments

+1 for a solution that is much shorter, easier to understand and more efficient than a foreach loop with a subroutine call on each iteration.
+1 for the same reasons, though it could be shortened considerably: map { join " ", sort split } @numbers should work.
@Jon Actually, no, that won't work. You still need a numeric sort - map { join " ", sort {$a <=> $b} split } @numbers.
@Telemachus: Darn. I guess my Perl is a tad rusty.
5

You have a list of items that you want to transform. That's a perfect candidate for map. Also note the default behavior of split: it operates on $_, splitting on whitespace, after removing leading whitespace.

my @array = ('6 8', '12 9 6', '33 32 5', '8 6');
@array = map { join ' ', sort {$a <=> $b} split } @array;

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.