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

I have a hash that is created in a loop
$foo{$bar} = [$rowArray[0],$rowArray[1]];
I can't figure out how to get a list of the keys which is sorted by the second element of the the array. Also $rowArray1 is a date and is in the format YYYY-MM-DD. I've tried to use the shwartzian transformation but I can't get it to work. Thanks for any help.

Replies are listed 'Best First'.
Re: sorting hash by value when value is an array ref
by jdporter (Paladin) on Nov 16, 2004 at 02:28 UTC
    @sorted_keys = sort { $foo{$a}[1] cmp $foo{$b}[1] } keys %foo;
Re: sorting hash by value when value is an array ref
by Zaxo (Archbishop) on Nov 16, 2004 at 02:31 UTC

    Here you go,

    my @sorted_keys = sort { $foo{$a}[1] <=> $foo{$b}[1] } keys %foo;
    (assuming numeric comparison is appropriate) [ Nope, alpha sort is correct, use cmp instead of <=>. I don't know how I missed that part of the question. ]

    After Compline,
    Zaxo

      I must say, I'm amazed by the quick response. This is my first questoin on this board. But back to the question. I had already been trying that bit of code the two of you posted and it doesn't seem to work. My list of keys still isn't sorted by the date. Any clue why? I also tried cmp and <=>.

        Update: Sorry, I see you've already done that.

        The code jdporter and Zaxo provided will indeed do what you ask. There's either an error in your description, or an error in the input you're using. Why don't you provide us a runnable snippet (complete with inputs) so we can continue to help you.

      cmp is what he is looking for, this will not fully work, as the element is a string not a number. jdporter got it right.

      Update:

      Zaxo already had this fixed before he saw my reply.

Re: sorting hash by value when value is an array ref
by ysth (Canon) on Nov 16, 2004 at 02:46 UTC
    Hmm. Since what should have worked didn't, can you show at least part of the output of:
    use Data::Dumper; print Dumper \%foo;
    and also copy and paste the exact code you are trying?
      foreach $homework (@homeworks) { $query = "SELECT PointValue,DueDate FROM Homework WHERE ClassID = +\'$courseID\' AND SectionID = \'$sectionID\' AND InstructorID = $ins +tructorID AND HomeworkName = \'$homework\'"; $statementHandle = $databaseHandle -> prepare($query); $statementHandle -> execute(); while(@rowArray = $statementHandle -> fetchrow_array()) { $homeworkHash{$homework} = [$rowArray[0],$rowArray[1]] +; } } # now the sorting my @sorted = sort { $homeworkHash{$a}[1] cmp $homeworkHash{$b}[1] } ke +ys %homeworkHash; # I then pass the @sorted to a template under the name homeworks and i +n the template I use this to print out the hash. [% FOREACH key IN homeworks %] <th valign="bottom" class="Homework"><span id="points">[% key +%]</span><br>[% homework.$key.0 %]<br>[% homework.$key.1 %]</th> [% END %]
      This doesn't print out a thing in the template. It is as if the @sorted in empty.
        Well, I don't know what all that non-Perl junk is... but I'm inclined to guess that [% FOREACH key IN homeworks %] is iterating over the keys in some other order, and that you're throwing away the result of the sort you so carefully set up. Do you know a way to set the key for iteration based on the contents of @sorted ?
Re: sorting hash by value when value is an array ref
by TedPride (Priest) on Nov 16, 2004 at 14:03 UTC
    for (sort {$foo{$a}[1] cmp $foo{$b}[1] or $a cmp $b} keys %foo) { print "$_ -> ['" . $foo{$_}[0] . "', '" . $foo{$_}[1] . "']\n"; }
    You have to have two comparisons, otherwise identical array values will result in keys being displayed out of order. I've included a print line to show how keys and values are accessed after the sort.