sub rekey { my $h = shift; KEY: for my $k (keys %$h) { if (ref $$h{$k} eq 'ARRAY') { rekey($_) for @{$$h{$k}}; my %n; for my $e (@{$$h{$k}}) { next KEY unless exists $$e{name}; die "duplicate key '$$e{name}'" if exists $n{$$e{name}}; $n{$$e{name}} = $e; } $$h{$k} = \%n; } elsif (ref $$h{$k} eq 'HASH') { rekey($$h{$k}) } } } rekey( $foo );