How do you sort the output of Data::Dumper?
Asked Answered
R

6

32

I want to dump the values of my object and hash, but it keeps printing the keys out of order. How can I dump the keys in (recursive) sort-order?

use Data::Dumper;
print Dumper $obj;
Rumrunner answered 19/9, 2011 at 5:34 Comment(0)
P
58

Set $Data::Dumper::Sortkeys = 1 to get Perl's default sort order. If you want to customize the order, set $Data::Dumper::Sortkeys to a reference to a subroutine that receives a reference to a hash as input, and outputs a reference to the list of the hash's keys in the order you want them to appear.

# sort keys
$Data::Dumper::Sortkeys = 1;
print Dumper($obj);

# sort keys in reverse order - use either one
$Data::Dumper::Sortkeys = sub { [reverse sort keys %{$_[0]}] };
$Data::Dumper::Sortkeys = sub { [sort {$b cmp $a} keys %{$_[0]}] };
print Dumper($obj);
Pressey answered 19/9, 2011 at 5:40 Comment(0)
D
15

Short answer for the impatient

Use Data::Dumper::Concise instead. It sorts your keys. Use it like this:

use Data::Dumper::Concise;

my $pantsToWear = {
    pony       => 'jeans',
    unicorn    => 'corduroy',
    marsupials => {kangaroo => 'overalls', koala => 'shorts + suspenders'},
};

warn Dumper($pantsToWear);

More words for the curious

Data::Dumper::Concise also gives you more compact, easier to read output.

Note that Data::Dumper::Concise is Data::Dumper with reasonable default configuration values set for you. Its equivalent to using Data::Dumper like this:

use Data::Dumper;
{
  local $Data::Dumper::Terse = 1;
  local $Data::Dumper::Indent = 1;
  local $Data::Dumper::Useqq = 1;
  local $Data::Dumper::Deparse = 1;
  local $Data::Dumper::Quotekeys = 0;
  local $Data::Dumper::Sortkeys = 1;
  warn Dumper($var);
}
Dragelin answered 19/9, 2011 at 8:18 Comment(1)
Nice for one-liners. But it's usually not installed by default. In Debian-based distributions, one can try sudo apt-get install libdata-dumper-concise-perlLed
L
6

From the Data::Dumper documentation:

$Data::Dumper::Sortkeys or $OBJ->Sortkeys([NEWVAL])
Can be set to a boolean value to control whether hash keys are dumped in sorted order. 
A true value will cause the keys of all hashes to be dumped in Perl's default sort order. 
Can also be set to a subroutine reference which will be called for each hash that is dumped. 
In  this case Data::Dumper will call the subroutine once for each hash, passing it the 
reference of the hash. The purpose of the subroutine is to return a reference to an array of 
the keys that will be dumped, in the order that they should be dumped. Using this feature, you 
can control both the order of the keys, and which keys are actually used. In other words, this 
subroutine acts as a filter by which you can exclude certain keys from being dumped. Default is  
0, which means that hash keys are not sorted.
Louvain answered 19/9, 2011 at 5:42 Comment(0)
C
6

You can set the $Data::Dumper::Sortkeys variable to a true value to get a default sort:

use Data::Dumper;
$Data::Dumper::Sortkeys  = 1;

my $hashref = {
    bob => 'weir',
    jerry =>, 'garcia',
    nested => {one => 'two', three => 'four'}};

print Dumper($hashref), "\n";

or put a subroutine in there to sort the keys however you want.

Conceivable answered 19/9, 2011 at 5:44 Comment(1)
this example is more clear than the other 2, i think other ppl looking for help with simple sorting will find ur answer the most useful!Rumrunner
L
2

For those who want to sort a hashref by value when printing it with Data::Dumper, here is an example:

$Data::Dumper::Sortkeys = sub {
    # Using <=> to sort numeric values
    [ sort { $_[0]->{$a} <=> $_[0]->{$b} } keys %{ $_[0] } ]
};

And here is a more readable alternative, doing the same but with a variable to hold the hash. It's less efficient, but for small hashes, some may find it nicer:

$Data::Dumper::Sortkeys = sub {
    my %h = %{$_[0]};
    # cmp for string comparisons
    [ sort { $h{$a} cmp $h{$b} } keys %h ];
};
Led answered 9/1, 2016 at 23:6 Comment(0)
T
2

sort ascii and full numeric:

$Data::Dumper::Sortkeys = sub {
  no warnings 'numeric';
  if(join('',keys %{$_[0]})=~/\d+/)
  {
    [ sort { $a <=> $b } keys %{$_[0]} ]
  }
  else
  {
    return [sort(keys %{$_[0]})];
  }
};
Tiebout answered 18/6, 2019 at 16:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.