简体   繁体   中英

How can I iterate through nested hash of hash without knowing its key?

I have a hash of hashes, that is, hash and hash references in my data structure. Can I iterate through the deepest hash when I only have the main hash name and no key of the deepest hash?

my %gates_info=(
    'order' => {
        'nand' => {
            'nand2_1' =>2,
            'nand2_5' =>-1,
            'nand2_4' =>2,
            'nand2_6' =>-1,
            'nand2_2' =>2,
            'nand2_3' =>3
        },
        'and' => {
            'and2'=>1,
            'and3'=>2,
        },
    }
);

sub max_gate_order {
    print values (%{$gates_info{'order'}});
    my @arr = (sort {$a <=> $b} values %{$gates_info{'order'}});
    return $arr[-1];
}

I want to iterate over the whole hash when I have just its name %gates_info and no keys such as "nand" or "and". What I am trying to achieve is to get the highest numeric value in each of the gates by sorting. Such as 3 in nand case and 2 in and case. Sub max_gate_order is used for sorting and returning highest value. Thanks

keys will give you those keys.

sub max_gate_order {
   my ($gates_info) = @_;
   my $max_order;
   my @gates;
   for my $gate_type (keys %{ $gates_info->{order} }) {
      for my $gate_id (keys %{ $gates_info->{order}{$gate_type} }) {
         my $order = $gates_info->{order}{$gate_type}{$gate_id};
         $max_order //= $order;
         if ($order >= $max_order) {
            if ($order > $max_order) {
               $max_order = $order;
               @gates = ();
            }

            push @gates, $gate_id;
         }
      }
   }

   return @gates;
}

my @gates = max_gate_order(\%gates_info);

The above returns all the gates with the highest order.

If you want both the gate type and the gate id, replace

push @gates, $gate_id;

with

push @gates, [ $gate_type, $gate_id ];

or

push @gates, [ $gate_type, $gate_id, $order ];

This is a longer, more redundant solution, more of an exercise really. But you might find it interesting to examine the structure of the hash iteration this way. (I know I do!) This could be useful if you have the main hash name ( %gates_info ), and none of the keys under that. 具有主哈希名称( %gates_info ),而该名称下没有任何键,则这可能很有用。 Which is what your question implies is the case. This pulls out all the key and value names as deep as the hash goes, in case any of those might be useful. I also uploaded a working example . (Note this does require knowing how many levels deep your hash is.)

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;


my %gates_info=(
    'order' => {
        'nand' => {
            'nand2_1' =>2,
            'nand2_5' =>-1,
            'nand2_4' =>2,
            'nand2_6' =>-1,
            'nand2_2' =>2,
            'nand2_3' =>3
        },
        'and' => {
            'and2'=>1,
            'and3'=>2,
        },
    }
);
print Dumper %gates_info;
print "\n\n";

my @gate;
my $hival; 

foreach my $gate (sort keys %gates_info) {
 foreach my $gatekey (sort keys %{$gates_info{$gate}}) {
   foreach my $deepkey (sort keys %{$gates_info{$gate}{$gatekey}}) {
   my $deepvalue = $gates_info{$gate}->{$gatekey}->{$deepkey};
push @gate, $deepvalue;
@gate = sort @gate;
$hival = $gate[@gate - 1];
print "Gate is $gate, gatekey is $gatekey, deepkey is $deepkey, deepvalue is $deepvalue\n"; 
  } 
print "\nGatekey is $gatekey, highest value is $hival\n\n";
@gate = (); #empty gate array
 } 
}

exit 0;

The output of the code is:

$VAR1 = 'order';
$VAR2 = {
          'and' => {
                     'and2' => 1,
                     'and3' => 2
                   },
          'nand' => {
                      'nand2_3' => 3,
                      'nand2_6' => -1,
                      'nand2_4' => 2,
                      'nand2_5' => -1,
                      'nand2_2' => 2,
                      'nand2_1' => 2
                    }
        };


Gate is order, gatekey is and, deepkey is and2, deepvalue is 1
Gate is order, gatekey is and, deepkey is and3, deepvalue is 2

Gatekey is and, highest value is 2

Gate is order, gatekey is nand, deepkey is nand2_1, deepvalue is 2
Gate is order, gatekey is nand, deepkey is nand2_2, deepvalue is 2
Gate is order, gatekey is nand, deepkey is nand2_3, deepvalue is 3
Gate is order, gatekey is nand, deepkey is nand2_4, deepvalue is 2
Gate is order, gatekey is nand, deepkey is nand2_5, deepvalue is -1
Gate is order, gatekey is nand, deepkey is nand2_6, deepvalue is -1

Gatekey is nand, highest value is 3
sub max_gate_order {

    my %hash =();
    foreach my $k (keys %{$gates_info{'order'}}) {
        my @arr = (sort {$a <=> $b} values %{$gates_info{'order'}->{$k}});
        $hash{$k} = $arr[-1];       
    }   
    return \%hash;

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM