MrFlibble has asked for the wisdom of the Perl Monks concerning the following question:

Hi all, I'm trying to work out where I'm going wrong with my data structures. I want to create a hash of lists of lists - i.e.
%datastructure=( 'foo' => [ [ 'foo01', 'foo02' ], [ 'foo11', 'foo12' ] ], 'bar' => [ [ 'bar01', 'bar02' ], [ 'bar11', 'bar12' ] ] );
From this, Data::Dumper gives me:
$VAR1 = 'foo'; $VAR2 = [ [ 'foo01', 'foo02' ], [ 'foo11', 'foo12' ] ]; $VAR3 = 'bar'; $VAR4 = [ [ 'bar01', 'bar02' ], [ 'bar11', 'bar12' ] ];
So far, so good. Now, what I want to do is shift out the first list from the 'foo' record, (i.e. return me the list ('foo01', 'foo02'), and remove that entry from the datastructure). The code I'm using for this is as follows:
my @entry = shift(@{@datastructure{'foo'}});
Now, this appears to work in that it removes the correct information from the data structure; however, rather than return it as a simple list, it returns it as a list which contains one element which is the list that I want (i.e. a LoL). This is confirmed by Data::Dumper - @entry is printed as:
$VAR1 = [ 'foo01', 'foo02' ];
Whereas creating a list manually:
@my_list = ('foo01', 'foo02');
gives:
$VAR1 = 'foo01'; $VAR2 = 'foo02';
So, how do I get my LoL into just a simple list?
Dumper(@entry);
gives:
$VAR1 = [ 'foo01', 'foo02' ];
whilst
Dumper(@entry->[0]);
also gives:
$VAR1 = [ 'foo01', 'foo02' ];
but
Dumper(@entry->[0]->[0]);
gives:
$VAR1 = 'foo01';
i.e. I can get either a LoL or a single element, but nothing inbetween. I'm confused!

Replies are listed 'Best First'.
Re: Data structures problem
by holli (Abbot) on Feb 20, 2006 at 14:11 UTC
    This behaviour is exactly as it should be, because your shift returns an arrayref. If you want it to be a plain list, dereference it:
    my @entry = @{shift(@{@datastructure{'foo'}})};


    holli, /regexed monk/
      Woohoo! It works!

      Thanks a lot. I've been trying every possible combination I could think of to get it to return what I wanted; I guess I never tried that one :-)

      I don't doubt that the behaviour is exactly as it should be, only that I didn't understand it ;-)

      Anyway, thanks for the solution. Would you believe I've spent nearly 2 days trying to sort this datastructure? I used to be really good at Perl (I've written big applications with large hashes of lists of lists of subroutine references etc...), but that was quite a few years ago, and now I rarely even need to use a simple unidimensional list.

      Forgive me, for I have sinned...

Re: Data structures problem
by davidrw (Prior) on Feb 20, 2006 at 14:20 UTC
    Assign the shift to an array ref instead of an array:
    my $entry = shift(@{@datastructure{'foo'}}); # it's an anrray ref print $_ for @$entry; # dereference it to get the array

    As you demonstrated w/Data::Dumper, You have a HoAoA .. note that by "array" it really is an array ref, which Dumper shows by using [ ] instead of ( ). So the first element of foo's array is an array ref ..

    A pointer w/using Data::Dumper -- always pass it a an array ref or hash ref instead of just an array or hash .. In this case it would have made the contents of @entry clearer (and Dumper(\%datastructure) would better illustrate the hashing):
    Dumper(\@entry); $VAR1 = [ [ 'foo01', 'foo02' ] ];
Re: Data structures problem
by planetscape (Chancellor) on Feb 20, 2006 at 15:23 UTC