http://www.perlmonks.org?node_id=35308


in reply to varying length multi-dimensional hashes

Since you're dealing with references, you can traverse your hash with a pointer-type of reference.
my %hash; while (<STDIN>) { chomp; my $pointer = \%hash; # start from root while (s/^(...)//) { # keep eating 1st 3 if ($_) { # if there's more to go, # we go deeper $pointer->{$1} = {} unless ref($pointer->{$1}); $pointer = $pointer->{$1}; } else { $pointer->{$1}++; # otherwise, set it to 1 } } }
Note that the following data will mess things up slightly:
111222333444555 111222333 $HASH{111}->{222}->{333} == 1 # lost 444 and 555 111222333 111222333444555 $HASH{111}->{222}->{333} != 1 # now a hash reference
These are unavoidable though with the criteria you've given. This code also assumes that your string will always be of a length that is divisible by 3. If you have two trailing characters at the end, the substitution will fail, but the test for $_ will have succeeded in the previous loop, giving you a dangling empty hash reference instead of 1.