I think this does what you want. It works in a similar fashion to your code by using a sort factory to return different sorting routines depending on what was requested. The sorting routines returned can cope with changes to the data structure. I have used an anonymous hash here but you could pass the sort factory a reference to the hash you are using through the rest of the code. Here is the data and the sort factory

use strict; use warnings; my $rhDataStruct = { q{URIBL_OB_SURBL+MPART_ALT_DIFF_COUNT} => { Total => 10, Value => 3.716 }, q{BAYES_00+FORGED_RCVD_HELO} => { Total => 5, Value => -2.464 }, q{BAYES_00+HTML_LINK_PUSH_HERE} => { Total => 1, Value => -2.202 }, q{SPF_HELO_PASS} => { Total => 16, Value => -0.001 }, q{BAYES_95+HTML_MIME_NO_HTML_TAG} => { Total => 1, Value => 4.082 } }; sub makeSorter { my $rhToSort = shift; my $sortType = shift || q{}; if ($sortType eq q{t}) { return sub { return sort { $rhToSort->{$a}->{Total} <=> $rhToSort->{$b}->{Total} } keys %$rhToSort; }; } elsif ($sortType eq q{v}) { return sub { return sort { $rhToSort->{$a}->{Value} <=> $rhToSort->{$b}->{Value} } keys %$rhToSort; }; } else { return sub { return sort keys %$rhToSort; }; } }

Here is the rest of the script that does some testing trying different sorts and adding to the data

my $rcDefault = makeSorter($rhDataStruct); my @sortedKeys = $rcDefault->(); printData(q{First default sort}); $rhDataStruct->{THIS_IS_A_NEW_ITEM} = {Total => 7, Value => 3.209}; @sortedKeys = $rcDefault->(); printData(q{Second default sort}); my $rcByValue = makeSorter($rhDataStruct, q{v}); @sortedKeys = $rcByValue->(); printData(q{First by Value sort}); $rhDataStruct->{ANOTHER_NEW_ITEM} = {Total => 13, Value => 2.873}; my $rcByTotal = makeSorter($rhDataStruct, q{t}); @sortedKeys = $rcByTotal->(); printData(q{First by Total sort}); @sortedKeys = $rcByValue->(); printData(q{Second by Value sort}); @sortedKeys = $rcDefault->(); printData(q{Third default sort}); sub printData { my $title = shift; print qq{\n$title\n}; for my $key (@sortedKeys) { print qq{$key\n}, qq{ Total - $rhDataStruct->{$key}->{Total}\n}, qq{ Value - $rhDataStruct->{$key}->{Value}\n}; } }

and here is the output

First default sort BAYES_00+FORGED_RCVD_HELO Total - 5 Value - -2.464 BAYES_00+HTML_LINK_PUSH_HERE Total - 1 Value - -2.202 BAYES_95+HTML_MIME_NO_HTML_TAG Total - 1 Value - 4.082 SPF_HELO_PASS Total - 16 Value - -0.001 URIBL_OB_SURBL+MPART_ALT_DIFF_COUNT Total - 10 Value - 3.716 Second default sort BAYES_00+FORGED_RCVD_HELO Total - 5 Value - -2.464 BAYES_00+HTML_LINK_PUSH_HERE Total - 1 Value - -2.202 BAYES_95+HTML_MIME_NO_HTML_TAG Total - 1 Value - 4.082 SPF_HELO_PASS Total - 16 Value - -0.001 THIS_IS_A_NEW_ITEM Total - 7 Value - 3.209 URIBL_OB_SURBL+MPART_ALT_DIFF_COUNT Total - 10 Value - 3.716 First by Value sort BAYES_00+FORGED_RCVD_HELO Total - 5 Value - -2.464 BAYES_00+HTML_LINK_PUSH_HERE Total - 1 Value - -2.202 SPF_HELO_PASS Total - 16 Value - -0.001 THIS_IS_A_NEW_ITEM Total - 7 Value - 3.209 URIBL_OB_SURBL+MPART_ALT_DIFF_COUNT Total - 10 Value - 3.716 BAYES_95+HTML_MIME_NO_HTML_TAG Total - 1 Value - 4.082 First by Total sort BAYES_95+HTML_MIME_NO_HTML_TAG Total - 1 Value - 4.082 BAYES_00+HTML_LINK_PUSH_HERE Total - 1 Value - -2.202 BAYES_00+FORGED_RCVD_HELO Total - 5 Value - -2.464 THIS_IS_A_NEW_ITEM Total - 7 Value - 3.209 URIBL_OB_SURBL+MPART_ALT_DIFF_COUNT Total - 10 Value - 3.716 ANOTHER_NEW_ITEM Total - 13 Value - 2.873 SPF_HELO_PASS Total - 16 Value - -0.001 Second by Value sort BAYES_00+FORGED_RCVD_HELO Total - 5 Value - -2.464 BAYES_00+HTML_LINK_PUSH_HERE Total - 1 Value - -2.202 SPF_HELO_PASS Total - 16 Value - -0.001 ANOTHER_NEW_ITEM Total - 13 Value - 2.873 THIS_IS_A_NEW_ITEM Total - 7 Value - 3.209 URIBL_OB_SURBL+MPART_ALT_DIFF_COUNT Total - 10 Value - 3.716 BAYES_95+HTML_MIME_NO_HTML_TAG Total - 1 Value - 4.082 Third default sort ANOTHER_NEW_ITEM Total - 13 Value - 2.873 BAYES_00+FORGED_RCVD_HELO Total - 5 Value - -2.464 BAYES_00+HTML_LINK_PUSH_HERE Total - 1 Value - -2.202 BAYES_95+HTML_MIME_NO_HTML_TAG Total - 1 Value - 4.082 SPF_HELO_PASS Total - 16 Value - -0.001 THIS_IS_A_NEW_ITEM Total - 7 Value - 3.209 URIBL_OB_SURBL+MPART_ALT_DIFF_COUNT Total - 10 Value - 3.716

I hope this is of use.

Cheers,

JohnGG

Update: Tidied testing code by putting repetitive prints into a subroutine.

Update 2: Corrected typo in updated code.


In reply to Re: Sorting a hash of a hash using anonymous subs by johngg
in thread Sorting a hash of a hash using anonymous subs by madbombX

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.