3

I have a HoH data structure. The outer level hash's keys are numeric - so I'd like to Dump the HoH numerically sorted by the first hash key (I don't care about the order of the inner hash). I've been trying different Sortkeys subs:

use Data::Dumper;
#$Data::Dumper::Sortkeys = sub { [sort { $a <=> $b } (keys %{$_[0]})] };  ## A
 $Data::Dumper::Sortkeys = sub { [sort { $a <=> $b } keys %$_ ] };       ## B
print Dumper(\%dsCmdBlocks);

I can't find the right syntax in the Sortkeys subroutine that will dump the HoH sorted by the first key numerically. When I try "A", it's sorts it fine for the first key, but it also spits out error messages saying that the inner arguments are not numeric (which is due to the use of [0]). So "A" is not the correct way to go. But, I can't figure-out how to sort on the first hash only.

By the way, when I send the HoH through a normal foreach loop using this:

foreach my $sk (sort {$a<=>$b} keys %dsCmdBlocks)
{
 print "KEY: $sk\n";
}

it works as I would expect.

How can I set up my Sortkeys sub to only sort on the first hash key?

toolic
  • 57,801
  • 17
  • 75
  • 117
CraigP
  • 453
  • 1
  • 3
  • 17
  • 1
    If you don't care whether the inner hashes are sorted, I assume it also wouldn't *hurt* if they were sorted. Why not just set `$Data::Dumper::Sortkeys` to `1` and *everything* will be sorted? – ThisSuitIsBlackNot Dec 02 '13 at 23:04
  • @ThisSuitIsBlackNot - that's what I originally was using (SortKeys = 1), but that apparently does a ASCII-type (cmp) of sort, not numeric (<=>). So when I had less then 10 hash elements, it appeared to be working, when in fact it really wasn't. – CraigP Dec 02 '13 at 23:56

1 Answers1

7

The callback for $Data::Dumper::Sortkeys operates on every hash reference found in the data structure, at any level. So you can either harden your sort routine against non-numeric inputs, like

$Data::Dumper::Sortkeys = sub {
    no warnings 'numeric';
    [ sort { $a <=> $b } keys %{$_[0]} ]
};

or apply some other machinations to see what your input looks like

$Data::Dumper::Sortkeys = sub {
    my $data = join '', keys %{$_[0]};
    if ($data =~ /[A-Za-z]/) {   # for example
        # input is not numeric
        return [keys %{$_[0]}];
    } else {
        return [ sort { $a <=> $b } keys %{$_[0]} ];
    }
};
mob
  • 117,087
  • 18
  • 149
  • 283
  • For not numeric keys string sort can be used too: return [sort keys %{$_[0]}]; – alex Dec 02 '13 at 23:51
  • @mob - thank you for clearing that up for me (i.e. "Sortkeys operates on every hash reference found in the data structure") - I was not aware of this! So in your 2nd solution: Two Question: 1.) in the 'join' stmt is that an empty space ''? 2.) for each level of hash reference the Dumper sub is called, correct? Another words in the stmt 'my $data = join '', keys %{$_[0]}; it's not grouping all the hashes for all levels all at the same time, right? – CraigP Dec 03 '13 at 13:05
  • 1) I wrote an empty string, but all I was trying to do is to put all of the keys of a hashref into one string so I can match it against a regex 2) correct. `$_[0]` is a reference to a single hashref at an arbitrary level of your data structure – mob Dec 03 '13 at 15:28