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

they both have to do with hashes. question the first: how do/can you sort hashes alphabetically? and, question the second: how do/can you run a loop that loops through two hashes? here's how they come together. some of you may have read it's been awhile . . ., but if not, you don't really need to. just putting this in unnecessary context :) anyway, at this stage i'm trying to print two hashes so i can look at them and see how they match up. i'd like to sort them before hand so comparing them would be much easier. here's what i've got for the sorting:
sort %filelist; sort %playlist;
and then for the printing:
for (keys %filelist) { print TEST $playlist{$_} . "\n"; print TEST2 $filelist{$_} . "\n"; }
now here's the two problems with those snipets. in the first one, it just doesn't sort. or, if it does, hardly the way i want. i need it alphabetically ordered, and when i look at the output, it . . . well . . . isn't. and then for the second part, what happens is that it'll print out filelist, but not playlist. if i say for (keys %playlist) instead, however, it prints playlist and not filelist. so essentially i need the two hashes sorted and some way of going through the keys for both hashes and printing them out. this is confusing because the sorting would work if they were arrays, would it not? and i just plain have no clue how to go about the second part. thanks in advance

Edit kudra, 2001-10-17 Changed title per ntc suggestion

Replies are listed 'Best First'.
Re: two questions that come together into one grand unified question
by premchai21 (Curate) on Oct 15, 2001 at 07:58 UTC

    No, the sorting would not work if they were arrays. Read sort again and you'll see why. Not only that, but hashes are by definition sorted by hash, that is, sorted in a manner only meaningful to the interpreter, probably not to you. However, arrays may or may not be sorted. The problem is that the sort function is non-destructive; it won't sort an array in place, but rather return a new array, which is sorted.

    Now as for the second problem, I assume you want to print to TEST the contents of playlist, and TEST2 the contents of filelist, with the keys sorted ASCIIbetically. Then you need two for loops:

    for (sort keys %playlist) { print TEST "$playlist{$_}\n" } for (sort keys %filelist) { print TEST2 "$filelist{$_}\n" }

    Now if you want the values sorted instead, then you need to do:

    for (sort values %playlist) { print TEST "$_\n" } for (sort values %filelist) { print TEST2 "$_\n" }

    HTH.

Re: two questions that come together into one grand unified question
by jryan (Vicar) on Oct 15, 2001 at 08:16 UTC

    This should work for you, if you wanted it sorted by values. If you wanted keys, just change the first for loop to add keys rather than values to the arrays. Enjoy.

    my @files; my @plays; for (keys %filelist) { $files[@files] = $filelist{$_}; $plays[@plays] = $playlist{$_}; } my @sorted = (0 .. $#files); @sorted = sort {$files[$a] cmp $files[$b]} @sorted; @files = @files[@sorted]; @plays = @plays[@sorted]; for (my $i=0; $i<@files; $i++) { print "$files[$i] \<\=\> $plays[$i]\n" }
      my @files; my @plays; for (keys %filelist) { $files[@files] = $filelist{$_}; $plays[@plays] = $playlist{$_}; }

      Just a small remark, you don't need a for-loop for that, I'd use values and a hash slice:

      my @files = values %filelist; my @plays = @playlist{ keys %filelist };

      -- Hofmator

Re: two questions that come together into one grand unified question
by jbert (Priest) on Oct 15, 2001 at 17:19 UTC
    Your actual question has been answered (sort the keys of the hash), but here is a little more commentary.

    You don't actually want to sort two hashes. No really, you said so. You want to compare two hashes. As you say, if a human is comparing them it is easier if they are sorted. But not if the computer is going to do it for you.

    Your longer term goal basically wants to take two hashes (%first and %second) as input and list:

    • keys in %second not in %first (@additions)
    • keys in %first not in %second (@deletions)
    • keys in both which have different values (@modifications)

    You can get the @additions or @deletions by looping through the keys of one hash and doing 'exists' test on the other. The situation is symettric and so you can write that bit as a helper routine and call it twice.

    You can get modifications by looping through the keys of either hash (not both) and doing nothing in the loop if the key is in either of the @additions or @deletions arrays. (You might want to invert the arrays into hashes to make an efficient "is this scalar in this array" test.)

    But you don't need the keys sorted in any of the loops described above.

    Have fun.

    PS. If efficency is your goal you can reduce the number of loops in what I have described above. But hey, optimising pseudo-code-written-in-english could be called premature.

Re: two questions that come together into one grand unified question
by IraTarball (Monk) on Oct 15, 2001 at 23:28 UTC
    I just wanted to put my spit in the pot too. So you know...
    %hash = sort %hash;
    is valid under strict but unlikely to do anything usefull. You get the hash flattened into a list, the list get's sorted, and then assigned to hash. A list assigned to a hash uses consecutive pairs and key/value pairs. I wrote a quick bit of code.
    use strict; use warnings; my %hash = ( thing1 => 'one thing', thing2 => 'leads to another', All => 'is great and glorious', ); print "$_ => $hash{$_}\n" for keys %hash; %hash = sort %hash; print "\n"; print "$_ => $hash{$_}\n" for keys %hash;
    Output is
    thing2 => leads to another All => is great and glorious thing1 => one thing leads to another => one thing thing1 => thing2 All => is great and glorious
    I can't think of a reason you would want to do this. I just wanted to throw it into this thread since it is kinda (but not really) used in the initial code.

    Goip,
    Ira,

    "So... What do all these little arrows mean?"
    ~unknown

Sorting a hash
by Anonymous Monk on Oct 16, 2001 at 11:48 UTC