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

Hey again Monks,
    I'm having some issues with sort. I have two arrays, @urls and @links, and I'd like to sort the links alphabetically. However, I can't do that because I can't figure out how to consequentially resort the urls as well.

Here's what I mean:

URLSLINKS
yahoo.comyahoo
ebay.comebay
google.comgoogle

now i want the sort function to sort both arrays such that it's:

URLSLINKS
ebay.comebay
google.comgoogle
yahoo.comyahoo

but if i can only make the sort apply to one array:

URLSLINKS
yahoo.comebay
ebay.comgoogle
google.comyahoo

I can figure it out if there's absolutely no way sort the both in the same order with SORT, it's just that a custom sort is a lot slower, and i'd need to do it a lot. I could also do it by putting them both in the same array delimited, but i still wish there was a way to do it in one step.

Replies are listed 'Best First'.
Re: Sorting issues
by The Mad Hatter (Priest) on Jul 23, 2003 at 03:43 UTC
    Use a hash instead of two arrays.
    my %foo = ( ebay => 'ebay.com', google => 'google.com', yahoo => 'yahoo.com' ); # The above hash assumes that no two links will ever be the same. # If they might be, but the URL isn't, just switch the order.
    Then sort on the keys.
    foreach my $link (sort keys %foo) { print qq[<a href="$foo{$link}">$link</a>]; }
Re: Sorting issues
by Abigail-II (Bishop) on Jul 23, 2003 at 08:19 UTC
    And here's a way that doesn't require you to start using a different datastructure:
    #!/usr/bin/perl use strict; use warnings; my @urls = qw {yahoo.com ebay.com google.com}; my @links = qw {yahoo ebay google}; my @s_ind = sort {$urls [$a] cmp $urls [$b]} 0 .. $#urls; @urls = @urls [@s_ind]; @links = @links [@s_ind]; print "@urls\n"; print "@links\n"; __END__ ebay.com google.com yahoo.com ebay google yahoo

    The code constructs an array with indices. First index is the position of the url that should come first, second index is the position of the url that should come second, etc, etc. Given that, sorting the urls and links happen in the same way.

    Abigail

Re: Sorting issues
by Zaxo (Archbishop) on Jul 23, 2003 at 03:44 UTC

    Associate the two with a hash,

    my %location; @location{@links} = @urls; print $_, ': ', $location{$_}, $/ for sort keys %location;
    or else make an AoA of them,
    my @locations = map {[$urls[$_], $links[$_]]} 0 .. $#urls; print join(': ', @$_), $/ for sort {$a->[1] cmp $b->[1]} @locations;

    After Compline,
    Zaxo

Re: Sorting issues (indices)
by tye (Sage) on Jul 23, 2003 at 08:11 UTC

    Using a hash works as already mentioned. For completeness, you should also know another standard trick. You can sort a list of indices:

    my @urls= qw( yahoo.com ebay.com google.com ); my @links= qw( yahoo ebay google ); my @idx= sort { $urls[$a] cmp $urls[$b] } 0..$#urls; # Now @urls[@idx] is sorted # and @links[@idx] is in the same order. # You could loop in that order like so: for my $i ( @idx ) { print "$urls[$i]\t$links[$i]\n"; } # Or you could just sort the arrays in place: @urls= @urls[@idx]; @links= @links[@idx];
    This trick can be useful for speeding up a lengthy sort operation. It is also a great way to keep one or more lists sorted in more than one order at once.

                    - tye
Re: Sorting issues
by bobn (Chaplain) on Jul 23, 2003 at 03:50 UTC

    At the time that you extract your links and URLs, create a single array the looks like (note: UNTESTED):

    @comb = ( [ 'ebay', 'ebay.com' ], [ 'yahoo', 'yahoo.com'], [ 'google', 'google.com'], );
    This can be done, for example:
    for ( @whatever) { # code that extracts URL and Link here push @comb, [ $link, Surl ]; }
    Then you can say:
    @bylink = sort {$a->[0] cmp $b->[0] } @comb; @byurl = sort {$a->[1] cmp $b->[1] } @comb;
    Then create your separate lists if you need them:
    @links = map { $_->[0] } @bylink; @urls = map { $_->[1] } @byurl;

    The map and sort operations can be chained. (This uses concepts form the Schwartzian transform.) I may be confusing what you call link and what you call URL, but I hope you get the point.

    --Bob Niederman, http://bob-n.com