There's more than one way to do things PerlMonks

### Sorting multi dimensional arrays

 on Mar 14, 2001 at 21:20 UTC Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Given a multi dimensional, what is the best way to sort the array numerically? eg:
```@array = ( [5,7,2],[9,4,8],[1,6,3]);
after sort results= ( [1,2,3],[4,5,6],[7,8,9] );
I have one solutions, but it kinda defeats the purpose, it completely disassembles the array and then rebuilds it. This seems to me as this would be slow and cumbersome and also limited to square tables.
```#!/usr/bin/perl
use Data::Dumper;

\$sample= [ [5,7,2],
[9,4,8],
[1,6,3]];

\$idx = \$#\$sample;

for (\$row=0; \$row <= \$idx; \$row++) {
if ( \$#{\$sample->[\$row]} != \$idx) {die "not a square table\n";}
else { push @unsorted, @{\$sample->[\$row]};}
}

@sorted = sort { \$a <=> \$b } @unsorted;

for (\$row=0; \$row <= \$idx; \$row++) {
my \$count = 0;
while (\$count <= \$idx) {
\$sample->[\$row][\$count] = shift @sorted;
\$count++;
}
}

print Dumper(\$sample);

Replies are listed 'Best First'.
Re: Sorting multi dimensional arrays
by arturo (Vicar) on Mar 14, 2001 at 21:49 UTC

If you have a multidimensional array, and you want to sort out the 'flattened' version (I'm wondering why you'd want to do this, but whatever), the most straightforward way is to flatten it out by writing a loop that grabs each element in each array reference and then sort the result:

```my @flatarray;
foreach (@twodimarray) {
foreach my \$element (@\$_) {
push @flatarray, \$element;
}
}
# for numeric data
@flatarray = sort { \$a <=> \$b } @flatarray;

This should work on *any* 2D array, whether the array references are all the same length or not.

You might check on CPAN (search for "Array") to see if someone's written a module that can help you.

Update I spoke too quickly ... so you want to reconstruct the array with the same dimensional structure as the original? well, take appropriate-sized slices of @flatarray and write them, as anonymous arrays, back into the original format (which is pretty much what you were doing). If you're dealing with more complex data (e.g. differing row lengths) you'll have to store the original row lengths (in an array) while you're flattening it out, and reconstruct the original array from that additional information.

Philosophy can be made out of anything. Or less -- Jerry A. Fodor

Re: Sorting multi dimensional arrays
by japhy (Canon) on Mar 14, 2001 at 23:11 UTC
You could sort each array reference individually, and then use some hybrid "merge" on them. But I'd suggest flattening them, and then unflattening them:
```my @flat = sort { \$a <=> \$b } map @\$_, @orig;
my @sorted = map [ \$orig[3*\$_ .. 3*\$_+2] ], 0 .. \$#flat/3;

japhy -- Perl and Regex Hacker
(tye)Re: Sorting multi dimensional arrays
by tye (Sage) on Mar 15, 2001 at 04:12 UTC
```my \$sample= [ [5,7,2], [9,4,8], [1,6,3] ];
my @widths= map 0+@\$_, @\$sample;
my @sort= sort map @\$_, @\$sample;
\$sample= [ map { [ splice @sort, 0, \$_ ] } @widths ];

But if you really wanted to not pull it apart to sort it:

```use mapcar;
my \$sample= [ [5,7,2], [9,4,8], [1,6,3] ];
my @refs= sort {\$\$a cmp \$\$b} map \(@\$_), @\$sample;
mapcar {
my( \$ref, \$val )= @_;
\$\$ref= \$val;
} \@refs, [ map \$\$_, @refs ];

Which requires that you grab my mapcar.

- tye (but my friends call me "Tye")
sorting a list of names into alphabetical orders using arrays
change cmp to <=>

rdfield

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

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (6)
As of 2019-04-22 15:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
I am most likely to install a new module from CPAN if:

Results (112 votes). Check out past polls.

Notices?