use strict ; use warnings ; use Data::Dumper ; my $source = { f1 => 'garbage', f2 => 'more garbage', f3 => 'important data', f4 => { this => 'sub hash', is => 'garbage' }, f5 => { f6 => 'more important data', f7 => { more => 'garbage', f8 => 'important data', }, f9 => 'garbage', }, f10 => [ 'important', 'data' ], f11 => [ 'more', 'garbage' ] }; my $filter = { f3 => 1, f5 => { f6 => 1, f7 => { f8 => 1 } }, f10 => 1 }; sub sliceTheWholeDarnThing { my $s = $_[0] ; my $f = $_[1] ; my $n = {} ; my @keysToGet = keys %{ $f } ; @{ $n }{ @keysToGet } = @{ $s }{ @keysToGet } ; foreach ( keys %{ $n } ) { if ( ref $n->{ $_ } eq 'HASH' ) { $n->{ $_ } = sliceTheWholeDarnThing( $s->{ $_ }, $f->{ $_ } ) ; } } return $n ; } my $newHash = sliceTheWholeDarnThing( $source, $filter ) ; print Dumper( $newHash ) ;