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

Dear monks,

I have a variable, $data, containing the following data (dumped by Data::Dumper):
$VAR1 = { 'article' => [ { 'SKU' => [ 'CDS00013' ], 'InternalSKU' => '179', 'AvailableItems' => [ '100' ] }, { 'SKU' => [ 'CDS00014' ], 'InternalSKU' => '180', 'AvailableItems' => [ '102' ] } ] };

As you can see, there are two "article" entries, each containing 3 fields of data. I want to process the data, but can't find a way to reach it. Any ideas? To make the code easy to maintain, I want to get a structure where I can access the data for each entry (so that I can use counters and such).

Replies are listed 'Best First'.
Re: Having trouble looping through a data structure
by biohisham (Priest) on May 16, 2010 at 17:17 UTC
    Invest time in reading about data structures, Perl Data Structure Cookbook -perldsc - can be a good start, these come in handy and they are not difficult but are not easy too...

    The function ref can allow you to make many useful decision with respect to the type of dereferencing task appropriate for a given segment of the data structure, for example, if 'ref' returned 'ARRAY' when you are looping through a hash you could probably access that particular array by dereferencing it as

    foreach my $element (@{$hash{$key}}{ #work on $element; }

    uncomment lines to see the returned value of 'ref' and compare that to the subsequent dereferencing approach chosen...
    use strict; use warnings; use Data::Dump qw(pp); my %hash; push @{$hash{'article'}},{}; $hash{'article'}[0]= {'SKU'=> ['CDS0013'], 'InternalSKU'=>'179', 'Avai +lableItems'=>['100']}; $hash{'article'}[1]= {'SKU'=> ['CDS0014'], 'InternalSKU'=>'180', 'Avai +lableItems'=>['102']}; foreach my $key (keys %hash){ #print ref $hash{$key},"\n"; foreach my $element (@{$hash{$key}}){ # print ref $element,"\n"; $articleCount = scalar @{$hash{$key}}; #get the coun +t ... foreach my $innerKey(keys %{$element}){ print "$element->{$innerKey}","\n"; #some mor +e referencing yet } } } print "there are $articleCount articles\n"; print pp \%hash;

    Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind.
Re: Having trouble looping through a data structure
by choroba (Cardinal) on May 16, 2010 at 16:35 UTC
    Try
    print $data->{article}[0]{SKU}[0];
    You can access all the entries this way. You should read perlref to understand what's going on.
      I can reach them like that without problems. I may have described my purpose in a bad way:-)
      I can put it like this, I want to find out how many articles there are, so that I loop through them. I.e, I want to be able to do this:
      loop over each article, how?? { print $data->{article}[i]{SKU}[0]; }
        for my $article (@{$data->{article}}) { print $article->{SKU}[0]; }

        I recommend perlreftut, it's easier to read and understand for the not-so-experienced.

        Perl 6 - links to (nearly) everything that is Perl 6.
Re: Having trouble looping through a data structure
by Khen1950fx (Canon) on May 17, 2010 at 01:28 UTC
    Lately, when I get bogged down in a structure, I use Data::TreeDraw. It helps. The only drawback perhaps is that it requires perl 5.10 or later. Here's a simplified script:
    #!/usr/bin/perl use strict; use warnings; use Data::TreeDraw; my $data = ['article' => { 'SKU' => [ 'CDS00013' ], 'InternalSKU' => '179', 'AvailableItems' => [ '100' ] }, { 'SKU' => [ 'CDS00014' ], 'InternalSKU' => '180', 'AvailableItems' => [ '102' ] } ]; print draw($data), "\n";
Re: Having trouble looping through a data structure
by Marshall (Canon) on May 16, 2010 at 19:17 UTC
    I am just guessing, but I figure that there are other things other than 'articles', maybe 'books' or whatever. One thing that might be considered is to take out one of the "levels of indirection" and add a field to the sub-hashes.
    my $AoH = [ { 'type' => 'article', 'SKU' => [ 'CDS00013', ], 'InternalSKU' => '179', 'AvailableItems' => ['100',], }, { 'type' => 'article', 'SKU' => [ 'CDS00014', ], 'InternalSKU' => '180', 'AvailableItems' => ['102',], }, { 'type' = 'book', 'SKU' => [ 'CDS00015', ], 'InternalSKU' => '220', 'AvailableItems' => ['103',], }, ];
    This can make sorting/searching much easier. An AoH in Perl works pretty much like an array of struct in C. And this can be translated into a DB with minimum fuss. Just an idea to consider.
Re: Having trouble looping through a data structure
by AnomalousMonk (Archbishop) on May 16, 2010 at 19:50 UTC

    One fishy thing about the example structure of the OP are sub-elements like
         'SKU' => [ 'CDS00013' ],
    and
         'AvailableItems' => [ '100' ]

    These imply there may be more than one value associated with each key, but I wonder if it is likely there will be more than one SKU number for a given item. If there will not be, don't put these elements in anonymous arrays.

    Of course, the OP example may just be an extreme simplification of a much more complicated structure. If so, it may be worthwhile considering a re-organization of the structure. For instance, if the 'InternalSKU' represents one or more actual, 'external' SKUs (say, from different suppliers, each with its own inventory count), might something like the following be more appropriate for maintainability:

Re: Having trouble looping through a data structure
by planetscape (Chancellor) on May 17, 2010 at 10:36 UTC
Re: Having trouble looping through a data structure
by leslie (Pilgrim) on May 17, 2010 at 10:14 UTC

    Dear friend,

    you can use this below code for accessing actual data..

    #!/usr/bin/perl + use strict; use warnings; use Data::Dumper; my ($hash); $hash = { 'article' => [ { 'SKU' => [ 'CDS00013' ], 'InternalSKU' => '179', 'AvailableItems' => [ '100', '200' ] }, { 'SKU' => [ 'CDS00014' ], 'InternalSKU' => '180', 'AvailableItems' => [ '102' ] } ] }; my($key_1,$value,$data); foreach my $key (keys %$hash){ foreach my $element (@{$hash->{$key}}){ while (($key_1, $value) = each %$element){ #print $key_1,"\n"; if(ref($value) eq "ARRAY") { foreach $data (@{$value}) { print "Actual hash of array data:$data\n" } }else { print "hash Value:$value\n"; } } } }