Sunella
Sunella

Reputation: 13

Perl: How do I get values of the nested hash sorted by the keys?

I am experimenting with a nested data structures in Perl these days. Let's say I have hash of array of hashes and I'd like to get values sorted by keys alphabetically. How do I do it?

The code:

#!/usr/bin/perl
use JSON::XS;
use Data::Dumper;
#use diagnostics;
use warnings;

my $school_data = {'School' => '156', 'Pupils' => [{'Person' => {name => 'Alice', age => 10, pet => 'cat'},'id' => 56},{'Person' => {name => 'John', age => 9, pet => 'dog'},id => 4}]};

print "\$school_data:" . Dumper ($school_data);

my $ref = $school_data->{Pupils};
foreach $pupil (@$ref){
    my @temp = sort (values $pupil->{'Person'});
    print "\n@temp\n";
}

Gives me an output:

    $school_data: $VAR1 = {
              'School' => '156',
              'Pupils' => [
                            {
                              'id' => 56,
                              'Person' => {
                                            'pet' => 'cat',
                                            'name' => 'Alice',
                                            'age' => 10
                                          }
                            },
                            {
                              'Person' => {
                                            'age' => 9,
                                            'name' => 'John',
                                            'pet' => 'dog'
                                          },
                              'id' => 4
                            }
                          ]
            };



10 Alice cat

9 John dog

And I wish to get values sorted by keys alphabetically (pet name age):

cat Alice 10

dog John 9

Looking forward to your help. Thank you.

Upvotes: 1

Views: 551

Answers (1)

Sobrique
Sobrique

Reputation: 53478

Hashes as I'm sure you know, don't store any sort of ordering, just key and value mappings.

But the sort function can take pretty much arbitrary code, that returns position dependant negative/0/positive to define sort order.

But you need to sort your 'top level' based on a subkey.

If you need to output values in a particular order - remember hashes are unordered you can use a slice.

So:

#!/usr/bin/env perl

use JSON::XS;
use Data::Dumper;

#use diagnostics;
use strict;
use warnings;

my @things = qw ( pet name age );

my $school_data = {
   'School' => '156',
   'Pupils' => [
      {  'Person' => { name => 'Alice', age => 10, pet => 'cat' },
         'id'     => 56
      },
      { 'Person' => { name => 'John', age => 9, pet => 'dog' }, id => 4 }
   ]
};

print "\$school_data:" . Dumper( $school_data->{Pupils} );

foreach my $pupil ( sort { $_ -> {Person} -> {name} 
                       cmp $_ -> {Person} -> {name} } 
                               @{ $school_data->{Pupils} } )
{
   print join " ", @{$pupil->{Person}}{@things}, "\n";
}

For multi-key sort, sort works just fine - provided the thing it returns is a numeric value.

So you could:

sort { $_ -> {Person} -> {name} cmp $_ -> {Person} -> {name}
    || $_ -> {Person} -> {age} <=> $_ -> {Person} -> {age}
    || $_ -> {Person} -> {pet} <=> $_ -> {Person} -> {pet} } 

Upvotes: 2

Related Questions