Question

Im trying to sort a HoAoH/Scalar, ignoring scalar entries at the beginning and just sorting the sub HASHes based on key.

From

$out = {
  'bgp 65000' => [
    ' undo synchronization',
    ' graceful-restart',
    ' peer 192.1683.0.1 as-number 65000',
    ' #',
    {
      ' ipv4-family vpn-instance client2' => [
        '  import-route direct route-policy BURrail'
      ]
    },
    '#'
    {
      ' ipv4-family vpn-instance internet' => [
        '  default-route imported',
        '  import-route direct',
        '  import-route static'
      ]
    },
    ' #',
    {
      ' ipv4-family vpn-instance client1' => [
        '  import-route direct route-policy BURrail'
      ]
    },
    ' #',
  ]
};

To

$out = {
  'bgp 65000' => [
    ' undo synchronization',
    ' graceful-restart',
    ' peer 192.1683.0.1 as-number 65000',
    ' #',
    {
      ' ipv4-family vpn-instance client1' => [
        '  import-route direct route-policy BURrail'
      ]
    },
    ' #',
    {
      ' ipv4-family vpn-instance client2' => [
        '  import-route direct route-policy BURrail'
      ]
    },
    '#'
    {
      ' ipv4-family vpn-instance internet' => [
        '  default-route imported',
        '  import-route direct',
        '  import-route static'
      ]
    },
    ' #',
  ]
};

I have written code to sort on the keys of the HASHES but was after a way to just sort the data structure on the fly.

use Sort::Naturally;

$key = ( sort keys %{ $out[0] } )[0];
foreach $key1 ( @{ $out[0]{$key} } ) { 
    if ( ref($key1) eq 'HASH' ) { 
        push @sorted, ( ( sort keys %{$key1} )[0] );
    } else {
        print "$key1\n";
    }   
}
foreach $key1 ( nsort(@sorted) ) { 
    print "$key1\n";
}
Was it helpful?

Solution

Tricky! (Because it's silly. You should be using a more convenient data structure. Anyway...)

First, let's ignore the irrelevant. We want to sort the elements of an array, so let's locate that array.

for my $array (values(%$out)) { ... }

Along the same lines, let's create a "view" that contains only the elements we want to sort. The following gives the indexes of the elements we want to sort:

my @idxs = grep { ref($array->[$_]) } 0..$#$array;

So the following is the "view" (array slice) we want to sort:

@{$array}[ @idxs ]

Each of these elements is a reference to a hash. We'll want to naturally sort the only key of the referenced hash. The key can be obtained using the following:

( keys(%$_) )[0]

Now, we just need to assemble the blocks.

use Sort::Key::Natural qw( natkeysort );

for my $array (values(%$out)) {
   my @idxs = grep { ref($array->[$_]) } 0..$#$array;

   @{$array}[ @idxs ] =
      natkeysort { (keys(%$_))[0] }
         @{$array}[ @idxs ];
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top