in reply to recursive hash layer removal question

This does an in-place edit of the underlying hash. With your $W above, you could flatten level 0 or 1. Flattening level 2 leaves it unchanged. Having other reference types intermingled will induce barfing.
sub do_for_level { my ($href, $level, $code) = @_; if ($level == 0) { %$href = map $code->($_, $href->{$_}), keys %$href if ref $href; } else { map do_for_level($_, $level-1, $code), values %$href; } } sub flatten_level { my ($key, $href) = @_; ref $href ? map {$_ => $href->{$_}} keys %$href : ($key, $href); } use Data::Dumper; do_for_level($W, 2, \&flatten_level); print Dumper($W);

Caution: Contents may have been coded under pressure.