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

hello, i have a question. i have two equal size arrays. they have one to one relationship. i want to sort one of them and keep the relationship. if i do this once, then i can use this array for the rest of the code so i dont want to deal with hash. instead of modifying a sorting algortihm from the beginning, is it possible with the "sort" function? to be clear let me write a simple example.
@a = qw (92 6 2); @b = qw (60 5 12); or equally @c = qw ( 92 60 6 5 2 12 ); what the result should be is; @c = (2 12 6 5 92 60);
i think, inserting map or grep function into sort function could do it, but i couldnt figure out how. can you help? thanks in advance.

Replies are listed 'Best First'.
Re: sorting two arrays together
by moritz (Cardinal) on Dec 22, 2010 at 22:09 UTC
    You can sort the indexes:
    my @index = 0..$#a; @index = sort { $a[$a] <=> $a[$b] } @index; my @sorted_a = @a[@index]; my @sorted_b = @b[@index]; use List::MoreUtils qw/zip/; my @combined_sorted = zip @sorted_a, @sorted_b;
      Good solution, but i'll try to reduce memory consumption of it:
      my @index = 0..$#a; @index = sort { $a[$a] <=> $a[$b] } @index; my @combined_sorted = map { $a[$_],$b[$_] } @index;
Re: sorting two arrays together
by Anonyrnous Monk (Hermit) on Dec 22, 2010 at 22:20 UTC

    In case you don't have a compelling reason to hold the data in two separate arrays, you could maybe also store the pairs as subarrays in one array:

    my @a = ([92,60], [6,5], [2,12]); my @sorted = sort { $a->[0] <=> $b->[0] } @a; # result: ([2,12], [6,5], [92,60])
      For small arrays, yes. Unfortunally, you'd be using a lot more memory when the arrays are large. There's quite a lot of overhead for an array. I'm not saying the OP shouldn't use pairs as subarrays, but he (or anyone else stumbling on this thread) should be aware of the possible downside.

        I always thought so, too.  Interestingly, according to Devel::Size, the memory usage isn't all that different:

        use Devel::Size qw(total_size); my @a; push @a, [$_,$_] for 1..2**16; print total_size(\@a); # one array of pairs my @b; push @b, $_ for 1..2**16; print total_size(\@b) * 2; # two arrays __END__ 4964080 4740496

        (tested with perl, v5.10.1 (*) built for x86_64-linux-thread-multi, Devel::Size-0.72)

        PS: although there is nothing random in the data, the sizes reported by Devel::Size vary by up to 15% from call to call (i.e. on some occasions the one array with pairs uses even less memory than two separate arrays). Why is that?

      moritz's way is very forward. but i will try this method too to learn. thank you both
Re: sorting two arrays together
by thargas (Deacon) on Dec 23, 2010 at 12:53 UTC
    you could also use zip from List::MoreUtils to get your @c, if that helps.
Re: sorting two arrays together
by furry_marmot (Pilgrim) on Dec 23, 2010 at 22:13 UTC
    It can be done in one step, using an index. This leaves the original untouched, in the manner the OP requested:
    use strict; my @a = qw (92 6 2); my @b = qw (60 5 12); my $i=0; my @c = map { $_->[0], $_->[1] } sort { $a->[0] <=> $b->[0] } map { [ $a[$i], $b[$i++] ] } @a; print join ' ', @c , "\n"; ## Prints 2 12 6 5 92 60

    Cheers!

    --marmot