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

I've got an array of anonymous hashes. Each hash has a string for a key. Each value of this hash is an anonymous hash keyed with numerical keys. I'm trying to use Dumper to print this data structure. I have the $Data::Dumper::Sortkey variable set to this subroutine:
sub hash_sort { my ($hash) = @_; return [ (sort {$a <=> $b} keys %$hash) ]; }
The problem is that this throws errors like 'Argument "apwu749_d5" isn't numeric in sort at update_settings.pl line 87' because it's trying to sort the hash keyed with a string numerically. What's the best way to modify this subroutine so it works for all kinds of hashes?

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon";
$nysus = $PM . $MCF;
Click here if you love Perl Monks

Replies are listed 'Best First'.
Re: Using Data::Dumpers Sortkeys subroutine
by almut (Canon) on Nov 27, 2008 at 07:18 UTC
    "apwu749_d5" isn't numeric in sort

    Maybe cmp instead of <=> ?

    (some sample data together with the expected (sorted) output might help...)

      Here is some sample data:
      $VAR3 = { 'apwu749_d5' => { '1' => 'anonymous user', '13' => 'Elected Officer', '17' => 'APWU Staff', '2' => 'authenticated user', '3' => 'member', '4' => 'web site committee', '5' => 'administrator', '9' => 'Shop Steward' } }; $VAR4 = { 'atu1700_drupal5' => { '1' => 'anonymous user', '2' => 'authenticated user', '3' => 'administrator', '4' => 'member', '5' => 'superuser', '6' => 'web site committee', '7' => 'steward', '9' => 'Executive Board Member' } };
      Notice how the numeric keys are sorted 1, 13, 17, 2, 3... in the first hash. That's what I'm trying to correct.

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon";
      $nysus = $PM . $MCF;
      Click here if you love Perl Monks

      Right, but what's the best way to make this subroutine intelligent enough to distinguish between a has with strings as keys and a hash with numeric values. The problem is Data::Dumper just blindly uses this subroutine for all hashes. I need to build intelligence into it so it knows which sort algorithm to use.

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon";
      $nysus = $PM . $MCF;
      Click here if you love Perl Monks

Re: Using Data::Dumpers Sortkeys subroutine
by nysus (Parson) on Nov 27, 2008 at 07:37 UTC
    I solved it with this less-than-ideal hack which works for this special case:
    84 sub hash_sort { 85 my ($hash) = @_; 86 if (ref %$hash != 'REF') { 87 return [ 88 (sort {$a <=> $b} keys %$hash) 89 ]; 90 } else { 91 return [ 92 (sort {$a cmp $b} keys %$hash) 93 ]; 94 } 95 }
    It tests to see if the value of the has is a reference to the anonymous hash. If not, it sorts it numerically, otherwise it gets sorted alphabetically. What would be a more robust way of solving this?

    $PM = "Perl Monk's";
    $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon";
    $nysus = $PM . $MCF;
    Click here if you love Perl Monks

      What would be a more robust way of solving this?

      I think natural sort - as Corion suggested - would fit the bill quite well:

      use Data::Dumper; use Sort::Naturally; $Data::Dumper::Sortkeys = sub { my ($hash) = @_; return [ nsort( keys %$hash ) ]; };
        Hmm, that results in an error:
        Bizarre copy of ARRAY in return at /usr/lib/perl/5.8/Data/Dumper.pm li +ne 511, <FH> line 130. Segmentation fault

        $PM = "Perl Monk's";
        $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon";
        $nysus = $PM . $MCF;
        Click here if you love Perl Monks