This sub will sort the output of Data::Dumper so that the hash keys are presented in sorted order. It is recursive and does all levels. Options include selection of alpha, numeric or automatic sort choice. Array elements can also be optionally sorted.
Update
Algorithm modified to to correctly handle AoH and AoA constructs as noted by AM
Update2
Gurusamy Sarathy writes:
Cute. However, the Data::Dumper that is in the latest Perl 5.7.x code base nicely supports sorting hashes. You can find it here:
http://public.ActiveState.com/gsar/APC/perl-current/ext/Data/Dumper/
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my %hash = (
x => 'line 1',
z => [ 1, 16, 4, 2 ],
y => { file=> 'test.txt',
length=> 200,
type => 'ASCII'
},
c => [ 'j', 'a', 'p', 'h' ],
b => [ {x => 1, a => 2, z => 3},
{1 => 'x', 2 => 'a', 3 => 'z'},
],
a => [ [0,1],[1,1],[-1,1],[-1,-1] ]
);
my $dump = Dumper(\%hash);
print "Sorted:\n", sort_dumper($dump,'auto',1);
print "\nRaw:\n", $dump;
# this sub will return sorted standard Data::Dumper output.
# an alphabetic sort is the default setting, example:
# sort_dumper( Dumper(\%hash) );
# numeric sort if called with a true second argument, example:
# sort_dumper( Dumper(\%hash), 1 );
# an automatic sort choice based on first char in first element
# is done if the second param is specified as 'auto', example:
# sort_dumper( Dumper(\%hash), 'auto' );
# arrays will be sorted if you pass a true third param
# example (alpha sort, including sorting array elements):
# sort_dumper( Dumper(\%hash), 0, 1 );
# to sort everything automatically you call it:
# sort_dumper( Dumper(\%hash), 'auto', 1 );
sub sort_dumper {
my ($dump, $numeric, $array) = @_;
my %pairs = $array ? ('['=>']', '{'=>'}') : ('{'=>'}');
# get opening details
my ($start, $open, $indent) = $dump =~ m/^(.+(.)\n)(\s*)\S/;
return $dump unless $open and exists $pairs{$open};
# get closing details
my ($close) = $dump =~ m/^(\s*$pairs{$open}.?\n)\z/m;
# get the key value assignments into an array
$dump =~ s/^\Q$start\E|\Q$close\E\z//g;
my @array;
push @array, $1 while $dump =~ m/^($indent(\S).*?)(?=^$indent(?:\2
+|\d)|\z)/msg;
$_ = sort_dumper($_,$numeric,$array) for @array;
# add trailing comma to last element
$array[-1] =~ s/\n$/,\n/;
# sort our key value chunks, numeric or alpha depending
# choose automatically if specified and use the Schzartzian
# transform for efficiency on numeric sort to get digits
$numeric = $array[0] =~ m/^\s*'?\d/ if $numeric eq 'auto';
@array = $numeric ? map{$_->[0]}sort{$a->[1]<=>$b->[1]}map{[$_,num
+($_)]}@array :
sort @array;
sub num { $_[0] =~ m/(-?\d+)/; $1 || 0 }
# remove trailing comma from (new) last element
$array[-1] =~ s/,\n$/\n/;
return join'', $start, @array, $close;
}
__END__
Sorted:
$VAR1 = {
'a' => [
[
-1,
-1
],
[
-1,
1
],
[
0,
1
],
[
1,
1
]
],
'b' => [
{
'1' => 'x',
'2' => 'a',
'3' => 'z'
},
{
'a' => 2,
'x' => 1,
'z' => 3
}
],
'c' => [
'a',
'h',
'j',
'p'
],
'x' => 'line 1',
'y' => {
'file' => 'test.txt',
'length' => 200,
'type' => 'ASCII'
},
'z' => [
1,
2,
4,
16
]
};
Raw:
$VAR1 = {
'x' => 'line 1',
'a' => [
[
0,
1
],
[
1,
1
],
[
-1,
1
],
[
-1,
-1
]
],
'y' => {
'length' => 200,
'file' => 'test.txt',
'type' => 'ASCII'
},
'b' => [
{
'x' => 1,
'a' => 2,
'z' => 3
},
{
'1' => 'x',
'2' => 'a',
'3' => 'z'
}
],
'z' => [
1,
16,
4,
2
],
'c' => [
'j',
'a',
'p',
'h'
]
};