use Data::Dumper; my $h = { 1 => { nick => 'rbush', phone => '5551212', bday => '3/12/1965', }, 3 => { nick => 'ernest', phone => '5553300', bday => '3/12/1971', }, 5 => { nick => 'fred', phone => '1112300', bday => '5/01/1972', }, }; sub hmap (&%) { my $code = shift; my @i = @_; local @_; my @rv; push @rv, $code->(@_=(shift @i,shift @i)) while @i; @rv; } my %new = hmap { $_[1]{nick} =~ /rbush|fred/ ? ($_[0], $_[1]) : () } %$h; my %new2 = hmap { $_[1]{nick} =~ /rbush|fred/ ? ($_[0], hmap { $_[0], $_[1] } %{$_[1]}) : () } %$h; print "new = " . Dumper (\%new) . "\n"; print "new2 = " . Dumper (\%new2) . "\n";