Description:

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'
                 ]
        };
Replies are listed 'Best First'.
Re: Sort Data::Dumper Output
by Anonymous Monk on Nov 27, 2001 at 03:36 UTC

    Unfortunately, you lose data if you dump AoH or AoA structures. Try this structure as a test case:

    my %hash = ( b => [ {x => 1, a => 2, z => 3}, {1 => 'x', 2 => 'a', 3 => 'z'}, ], a => [ [0,1],[1,1],[-1,1],[-1,-1] ], );