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

Hello Wise Monks,

I am trying to sort a hash ref by the date field old_file in the ref. Below is a Data::Dumper of one of the fields in the ref. I have done some reading and googling on sorting hash refs and it is all very confusing to me. Still not even sure if it is possible to sort by date. I'm still pretty new to perl. Any code snippets or directions to some good reading material would be very much appreciatated.
'88959b2c541a8854042ef52b45af1075' => { 'files' => [ { 'file_type' => +1, 'date_uploaded' + => '2005-10-25', 'file_name' => +'Name of file.tif', 'date_faxed' => + '' }, { 'file_type' => +2, 'date_uploaded' + => '2005-10-25', 'file_name' => +'some file 823144 N.pdf', 'date_faxed' => + '2005-10-25' } ], 'phone' => 'xxx-xxx-xxxx', 'last_name' => 'Doe', 'dme_num' => '123456', 'old_file' => '2005-10-25', 'dme_pid' => '938edfd95dd42a58 +786330bb8c85f479', 'first_name' => 'John' },
** Edit ** Found the answer between not accessing the hash ref correctly and not being able to sort hashes without proper modules. The answer lied (layed?) in doing the sort with my print. Code to follow.
foreach my $key (sort { $patients->{$a}->{old_file} cmp $patients->{$b +}->{old_file} } (keys %{$patients})) { # print ... }
Big thank you to all the monks that replied. Never ceases to amaze me the level of help I get here.

Replies are listed 'Best First'.
Re: Sorting a Hash Ref
by metaperl (Curate) on Oct 26, 2005 at 16:44 UTC
    Sure you can! The sort docs give a similar case and you can always step up to the various sorts discussed in "Data Munging with Perl" if you really want high-octane performance.
    my %sorted = sort { $a->{old_file} cmp $b->{old_file} } (keys %{$hashref}); my $sorted = \%sorted; # or put { } around the sort expression to do it one line.
    This assumes the month and day fields are both always 2-characters wide. If they are not, then visit CPAN,/a> and find a Date module to do the comparision.

    For example Date::Manip has a Date_Cmp function, whose docs say:

    This takes two dates and compares them. Almost all dates can be compared using the perl "cmp" command. The only time this will not work is when comparing dates in different timezones. This routine will take that into account.
      my %sorted = ....

      Everybody repeat after me: YOU CAN NOT SORT A HASH!

      Hashes are unordered. Attempting to sort them just gets you a list which is stuffed back into a hash which has no internal order. You can get a sorted list of keys or values, but you can not sort a hash.

        Everybody repeat after me: YOU CAN NOT SORT A HASH!

        Hm, okay... YOU CAN NOT SORT A HASH!

        Seriously, though, Tie::IxHash.

        Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }


        Perl 6 changes:

        • Ordered hashes will probably&hopefully be more accessible, and standard. This isn't certain yet.

      The dates should always remain 2 characters. But I keep running into an error when I run the script.
      Can't use string ("57e27be8194bb2332a49a942e7aeafeb") as a HASH ref wh +ile "strict refs" in use at ...
      Any ideas on what I'm doing wrong?

        That string, "57e27be8194bb2332a49a942e7aeafeb", is your key (as shown in your original post.) You are trying to use the key itself as a hash ref. You can't do that. You need to look up the hash ref stored in your hash at that key. I.e. you are doing something like $key->{old_file} where you need to be doing something like $yourhash{$key}->{old_file} or possibly $yourhashref->{$key}{old_file}. It's impossible to tell which from your post because you don't show us whether you access your top level hash directly or through a reference.

        -sauoq
        "My two cents aren't worth a dime.";
        
        Well, that is true. What are you not telling us here? That Dumper output doesn't look right. Is that just part of the dump?
Re: Sorting a Hash Ref
by Juerd (Abbot) on Oct 26, 2005 at 20:02 UTC

    If you have a hash reference $foo, then the hash is %{$foo}. This is all need to you know, if you know how to use a hash.

    %foo %{$bar} @foo{...} @{$bar}{...} $foo{...} ${$bar}{...}
    If the reference is in a normal scalar variable, you can leave out the first set of {}, so you get %$bar, @$bar and $$bar. As a special case, $$bar{...} can be written as $bar->{...}. This arrow notation is the preferred method.

    Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }


    Perl 6 changes:

    • The sigil no longer changes with use. A hash gets % in all three cases, instead of %, @ or $, depending on how it is used.
    • A hash returns a list of pairs in list context.
    • Sorting by something only requires specifying that something: sort { .key }, %hash, sort { .value }, %hash.
    • You can use the reference as if it were a normal hash, and Perl 6 automatically dereferences it for you. In list context, though, you have to dereference explicitly with %$foo, or specify explicitly that you want a list of pairs: $foo.pairs.
    • Arrows are now dots, and in the case of hash references, can even be left out entirely.

      Perl 6 sounds like it has some nice features.