This is my method for sorting parallel arrays. It needs some work because it's very slow. Any help is appreciated.
sub parasort (&@) { my($coderef, $master_array, @arrayrefs) = @_; my(%hash, @final); @{$final[0]} = sort {&$coderef;} @{$master_array}; foreach my $m (0 .. $#{@{$master_array}}) { foreach my $s (0 .. $#arrayrefs) { push @{$hash{$$master_array[$m]}[$s];}, $arrayrefs[$s][$m] +; } } foreach my $m (sort {&$coderef;} keys %hash) { $t = 1; foreach my $s (@{$hash{$m};}) { push @{$final[$t]}, @{$s}; ++$t; } } return @final; } my @array1 = (10, 9, 8, 7, 6, 5, 5, 3, 2, 1); my @array2 = ( 3, 6, 2, 5, 6, 7, 8, 3, 2, 5); my @array3 = ( 4, 6, 7, 4, 3, 2, 5, 7, 8, 9); my ($array1, $array2, $array3) = parasort { $a <=> $b } \@array1, \@ar +ray2, \@array3; #returns arrayrefs

Replies are listed 'Best First'.
Re: Parallel Array Sorting
by diotalevi (Canon) on May 03, 2004 at 23:58 UTC

    See fast, flexible, stable sort. I've translated your code using that idea.

    sub parasort { my $sort = shift; my $independent_array = shift; my @dependent_arrays = @_; my @sort_ix = map unpack( 'N', substr( $_, -4 ) ), sort map &$sort( $independent_array->[ $_ ] ) . pack( 'N', $_ ), 0 .. $#$independent_array; return map [ @{ $_ }[ @sort_ix ] ], $independent_array, @dependent_arrays ; }
      This is indeed faster, but it should be noted that the meaning of the code-ref that's passed in is quite different than in the OP... Rather than being a sort function, this version uses the code-ref as a transform used to convert the source values into a bytewise-sortable format. This can be a big performance win, as has been discussed elsewhere, but does require a bit of fiddling to be convert the calling code from the approach used by the OP.
Re: Parallel Array Sorting
by simonm (Vicar) on May 04, 2004 at 16:40 UTC
    This appears to be around twice as fast with your sample data, and should be even faster for larger arrays:
    sub fast_parasort (&@) { my($coderef, $master_array, @arrayrefs) = @_; my @indexes = sort { local ($a, $b) = ( $master_array->[$a], $mast +er_array->[$b] ); &$coderef } ( 0 .. $#$master_array ); map { [ @$_[ @indexes ] ] } ( $master_array, @arrayrefs ); }

    The biggest distinction is that it avoids creating intermediate hashes and arrays -- instead, it just figures out the sorted order of the indices, based on your first array, and then uses slices to return the sorted version of all of the arrays.

      Wow, I knew there had to be a much easier way. Thank you very much. This is some very nice code. I could never write this. If this is just twice as fast, it's about a million times cleaner. Thanks again.
      -Will