my $next = hash_walker(\%data); while (my @row = $next->()) { print join(',', @row), "\n"; } sub hash_walker { my ($href) = @_; die "Not a hash ref" if ref($href) ne 'HASH'; my (@ref, @key) = ($href, ()); while (ref($href) eq 'HASH') { my ($key, $val) = each %$href; push @key, $key; push @ref, $val; $href = $val; } my ($val, $done) = (pop @ref, undef); return sub { return () if $done; my @row = (@key, $val); my ($k, $v) = each %{$ref[-1]}; if (defined $k) { ($key[-1], $val) = ($k, $v); return @row; } my $idx = $#ref; while ($idx--) { my ($k, $v) = each %{$ref[$idx]}; next if ! defined $k; $key[$idx] = $k; $ref[$idx + 1] = $v; for ($idx + 1 .. $#ref) { my ($k, $v) = each %{$ref[$_]}; $key[$_] = $k; $ref[$_ + 1] = $v; } $val = pop @ref; return @row; } $done = 1; return @row; }; }