SPUG: Slice of HashOfHash

Paul Goracke paul at goracke.org
Wed Nov 15 16:51:44 PST 2006

Eric.D.Peterson at alltel.com wrote:

> How can I make a new hash  or loop through this HoH where husband = 
> "fred"? 
> I've been reading up on slices and printing hashes, but I can't seem to 
> find an example or description on playing with HoH subsets.  I've tried 
> looping through the full HoH and adding those desired elements to a new 
> HoH but that seems awkward and not quite right & cumbersome.  So I 
> thought I'd ask ya'll for some help.

Many ways of doing it, all of which use a loop/map/grep that I can think 
of. Two I can think of w/ your current data structure (I'm a bit 
paranoid about checking for a defined key before string comparing):

# grep filter for entries with 'husband'='fred',
# then add that key and its hashref
my %sub = map { $_ => $HoH{$_} }
grep { $HoH{$_}{'husband'} && $HoH{$_}{'husband'} eq 'fred' }
keys %HoH;

# or loop through w/ 'each', which makes it easier to follow the key/obj
my %sub2 = ();
while ( my ($key,$obj) = each %HoH ) {
     $sub2{$key} = $obj
	if ( $obj->{'husband'} && $obj->{'husband'} eq 'fred' );

In a case like this, I tend to "smuggle" the key into the object hashref 
itself so I can operate on just the hashref, instead of trying to keep 
track of the key and ref--if you change your data by:

while ( my ($key,$obj) = each %HoH ) {
     $obj->{'_key'} = $key;

you can then do:

my %sub3 = map { ($_->{'husband'} && $_->{'husband'} eq 'fred')
		 ? ( $_->{'_key'} => $_ ) : () }
		 values %HoH;

# or

my %sub4 = ();
$sub4{$_->{'_key'}} = $_
	for grep { $_->{'husband'} && $_->{'husband'} eq 'fred' }
		values %HoH;


More information about the spug-list mailing list