if(ref($hash) eq 'HASH'){ my $header = $hash->{'header'}; while(my ($key, $value) = each(%$hash)){ push(@stack, unpack_row($value, (@row, $key))); } } else { return([@row, $hash]); } #### if(ref($hash) ne 'HASH'){ return([@row, $hash]); } my $header = $hash->{'header'}; while(my ($key, $value) = each(%$hash)){ push(@stack, unpack_row($value, (@row, $key))); } #### use strict; use warnings; use Data::Dumper; sub unpack_row { my ($hash, @row) = @_; return [ @row, $hash ] unless (ref $hash eq 'HASH'); return map { unpack_row($hash->{$_}, @row, $_) } keys %$hash; } my $hash = { foo => { bar => { bat => 5, bird => 2 } }, goo => { tab => { bird => 2 } }, }; print Dumper($hash); print Dumper(unpack_row($hash, ()));