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

I have a list of indices from an array that was numerically sorted. I would like to sort the second dimension of a 3 dimensional array:
#construct 2D array for (my $e = 0; $e < @dim1; $e++) { $arr_1[$e] = [ @array ]; } # fill array for (my $i = 0; $i < 10; $i++) { @tmp_array = undef; for (my $e = 0; $e < @suff; $e++) { $tmp_array[$e] = $e; } push @{ $arr_1[$i] }, [ @tmp_array ]; } # Get the indices from the sorted list @indices = sort { $arr2sort[$a] <=> $arr2sort[$b] } 0..$#arr2sort; # Sort the 3D array? for (my $e = 0; $e < @suff; $e++) { @{ $arr_1[$i] } = @{ $arr_1[$i][@indices] }; }
This code continues to give the error: Can't use an undefined value as an ARRAY reference at analyze.pl for the sorting routine. How can I sort the second dimension of @arr_1? Is @arr_1 a 3D array in the way that I have coded it?

Replies are listed 'Best First'.
Re: Sorting multidimensional arrays using a list of indices
by GrandFather (Saint) on Sep 10, 2009 at 02:22 UTC

    @{ $arr_1[$i][@indices] } should be @{$arr_1[$i]}[@indices] if you want to return a slice with the element order determined by @indices. Although you don't reference the line where the error is being reported nor give us enough code to actually reproduce your error, that is most likely where the issue is.

    Aside from that, your final loop uses $e as a loop variable, but @arr_1 is indexed by the undeclared variable $i. Always use strictures (use strict; use warnings; - see The strictures, according to Seuss)!

    Using Perl there are very few places where you need to resort to using a C for loop. Use a Perl for loop instead:

    for my $i (0 .. $#suff) {...}

    although the last loop in your sample code might be better written:

    for my $elt (@arr_1) { @$elt = @{$elt}[@indices]; }

    or even

    @$_ = @{$_}[@indices] for @arr_1;

    True laziness is hard work
      Your initial comment was correct! Thanks for your help, been struggling with multidimensional arrays / sorting for too long.
Re: Sorting multidimensional arrays using a list of indices
by Marshall (Canon) on Sep 10, 2009 at 03:08 UTC
    Not quite sure about the type of data structure that you intend. The code below would sort on 2nd column of matrix with 3 columns.
    #!/usr/bin/perl -w use strict; use Data::Dumper; my @AoA = ([1,2,3], [1,1,3], [1,5,2], [0,-1,3] ); print Dumper(\@AoA); @AoA = sort{@$a[1] <=> @$b[1] }@AoA; print Dumper(\@AoA);
    Part of my "non-understanding" is: I have a list of indices from an array that was numerically sorted. The natural thing would be to have that array in the sorted order! I don't understand why I should mess with: thing 15 should be in the place thing 2 is in now, etc. If the array is sorted, then I don't need the indices. The array is just going to be sorted further.

    Can you write a simple Perl variable declaration with the type of structure that you want to sort? Something like this would be a "3D" thing.

    my @AoAoA = ( [ [1,2,3] ,[1,1,3],[1,5,2] ], [ [0,-1,3],[1,5,2],[3,2,1] ], [ [0,-1,3],[1,-1,3],[5,4,2] ], );
    In Perl something like that or even what I showed above for a matrix is rare. The closest Perl equivalent to a 'C' 2D array is an array of hash. The reason is that this avoids all this index 1 really means NAME sort of stuff.