Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Foreach hash of array

by rose (Beadle)
on Aug 05, 2008 at 15:01 UTC ( #702383=perlquestion: print w/replies, xml ) Need Help??
rose has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

I want to use foreach for the following refrence.

use warnings; use strict; my $xml = { 'Fruits' => [ { 'Season' => { 'Apple' => { 'UnitsAvailable'=> ['100'] }, 'Orange' => { 'UnitsAvailable' => ['200'] } } } ] };

Please help on this


Replies are listed 'Best First'.
Re: Foreach hash of array
by Corion (Pope) on Aug 05, 2008 at 15:04 UTC

    Maybe you can tell us what you want to achieve, what makes you think that foreach is the right tool for that goal, and what problems are stopping you?

    foreach ($xml) { print; };

    works as expected for me.

    Update: kyle spotted a broken link, fixed

Re: Foreach hash of array
by Fletch (Chancellor) on Aug 05, 2008 at 15:19 UTC

    Maybe if you post the same terribly worded question yet a third time then you'll get an answer. I mean don't bother reading How (Not) To Ask A Question or giving a cogent description of what you're actually trying to do, next time just post the data structure you've got followed by a "?" and you'll surely get help then. Third time's a charm, they say.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      Ironically, the first post was better. It contained a statement of a goal, "to find the child keys of 'Orange'". The goal was not clearly defined however.

      A third post may be reminiscent of the final scene in the Vincent Price version of The Fly and consist of only the words "Help me".

      TGI says moo

Re: Foreach hash of array
by TGI (Parson) on Aug 05, 2008 at 17:50 UTC

    You are getting a bad response because your questions are not clear and do not show any actual attempt to solve the problem.

    You will get a better result if you clearly state what your goal is, show a sample of failed code, and describe the error/bad result from your attempt. Read the How (Not) to Ask a Question node linked elsewhere in the thread.

    For example, if you had said, "I need to iterate over the array reference stored in the 'Fruits' key and find all cases where the grandchild key is 'Orange'. Here's what I've tried: ... some code goes here...", you would probably have an answer by now.

    Your questions make giving you the answer you want impossible. Nobody really knows what you really want. Someone might hit on it in with a lucky guess, but do you want to rely on an improbable chance?

    Here's where I take a guess at helping you. Your variable name is '$xml'. Are you getting this data structure from an XML file? It's a needlessly complex structure. What tools are you using to parse the XML? Maybe a different library would be helpful. There are tons of libraries for XML munging that may make solving your problem trivial. If the data doesn't come from an XML file, you may wish to change your variable name, and simplify the data structure.

    Update: Take a look at Iterating over an array variable times for an example of an unclear question followed up by a good problem statement.

    TGI says moo

Re: Foreach hash of array
by hangon (Deacon) on Aug 05, 2008 at 17:43 UTC

    Between this and your first post, maybe there is enough info to infer what you're looking for. First some tips:

    • Please state your question clearly and with enough information that others can understand what you're looking for.
    • Don't post the same question twice, it only irritates people. If you have more to add, just update your original post - and say that you added an update.
    • As suggested by Fletch please read How (Not) To Ask A Question. Help us help you.

    With that out of the way, you are dealing with a nested data structure with several levels. Foreach will only iterate over only one level at a time.

    # first, create a reference to the level you are interested in. my $oranges = $xml->{Fruits}->[0]->{Season}->{Orange}; # then do whatever you need to with it, ie: foreach (keys %$oranges){ ...

    To better understand this stuff, please read Nested Data Structures and Perl Data Structures Cookbook.

Re: Foreach hash of array
by jethro (Monsignor) on Aug 05, 2008 at 15:19 UTC
    To loop through a hash you have the reference to, use

    foreach my $f ( keys %$xml ) { ... $xml->{$f} ... }
    Now this will loop only through the highest hierarchy of your construct, so $f will be 'Fruits' and then the loop is already finished. To get to the data underneath you have to recursively descend or know exactly what you are looking for.

    Please be more specific when asking questions. You also might read a book on data structures.

Re: Foreach hash of array
by cdarke (Prior) on Aug 05, 2008 at 15:36 UTC
    For what its worth, this works:
    sub printit { my $ref = shift; foreach my $key (keys %$ref) { print "$key: "; if (ref $ref->{$key} eq 'ARRAY') { if (ref $ref->{$key}[0]) { printit($ref->{$key}[0]) } else { print "$ref->{$key}[0]\n" } } elsif (ref $ref->{$key} eq 'HASH') { printit ($ref->{$key}) } else { print "$ref->{$key}\n" } } } printit ($xml);
    But I don't know if it gives what you want, 'cause I don't know what you want.
Re: Foreach hash of array
by ikegami (Pope) on Aug 05, 2008 at 16:50 UTC

    Using "foreach" or "grep" on a hash makes no sense. Tell us what you want to do, not how you want it to be done!

    If want to enumerate the fruits in season (totally ignoring vegetables and fruits that aren't in season), you could use the following:

    my $fruits_in_season = $xml->{Fruits}{Season}; for my $fruit_name (keys %$fruits_in_season) { my $fruit = $fruits_in_season->{fruit_name}; ... }

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://702383]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (2)
As of 2017-04-25 04:24 GMT
Find Nodes?
    Voting Booth?
    I'm a fool:

    Results (449 votes). Check out past polls.