use strict; use warnings; use Algorithm::Loops qw( NestedLoops ); my %data = ( fruit => [qw( apple pear )], type => [qw( farmed organic )], period => { 20050824 => { to => [ 'new york', 'london' ], }, 20050825 => { to => [ 'auckland' ], }, } ); my $iter = NestedLoops([ $data{fruit}, $data{type}, [ keys %{$data{period}} ], sub { $data{period}{$_[2]}{to} }, ]); my @expanded; while (my @list = $iter->()) { my %row; @row{qw( fruit type period to )} = @list; push @expanded, \%row; } require Data::Dumper; print(Data::Dumper::Dumper(\@expanded));