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

I have a hash (i believe it to be a hash) with data that looks like the following:
Dumping$VAR1 = { 'data' => [ { 'ID' => 32, 'State' => 'Stopped' }, { 'ID' => 33, 'State' => 'Stopped' }
I want to be able to loop through the data, and check the current JobID, when i find a match (say 33) i want to grab the State field and do a check against it. How would this be possible? I tried the following:
foreach my $value (sort keys $states->{data}) { if ($value == 15) { $CurrentState = $states->{data->{'State}'}; print "In here because found state of 15\n"; print "CurrentState; [$CurrentState]\n"; } }
Which prints the CurrentState - but its blank as im accessing it incorrectly. So i am able to get to the point where i know JobID = 15, but i can't get the current state field correctly. Cheers

Replies are listed 'Best First'.
Re: accessing data in hash
by kcott (Archbishop) on Mar 29, 2014 at 10:46 UTC

    G'day ccfc1986,

    Welcome to the monastery.

    "I have a hash (i believe it to be a hash) ..."

    That's a fundamental concept that you should understand. Start by reading "Perl introduction for beginners".

    Your data contains references ([...] and {...}) which you'll need to handle. "Perl references short introduction" should provide sufficient background for what you'll need here.

    You're dealing with a complex data structure. Read "Perl data structures intro" to understand this part of your code.

    By now you should have a good idea about you've been doing wrong. Simple typos in your code may still result in buggy code (i.e. invalid logic but still valid syntax) which aren't immediately obvious. As you would have read from that first link I provided, let Perl find these problems for you, by adding these two lines to the top of all your scripts:

    use strict; use wanings;

    You haven't shown sufficient code, output, error/warning messages, etc. to know what a correct solution would be. The guidelines in "How do I post a question effectively?" describe what information to provide such that we can more easily help you.

    If you really are dealing with a hash, then the code you'll need to meet your described requirements would be something like this:

    for (@{$your_hash{data}}) { if ($_->{ID} == $current_job_id) { # Do your checks on $_->{State} here last; } }

    As you can see, that looks nothing like the code you posted. Given the lack of information I've already mentioned, that's my best guess.

    -- Ken

Re: accessing data in hash
by 2teez (Vicar) on Mar 29, 2014 at 05:39 UTC

    Hi ccfc1986,

    ..I want to be able to loop through the data, and check the current JobID, when i find a match (say 33) i want to grab the State field and do a check against it..

    You mean something like so:

    print map { $_->{State} if $_->{ID} == 32 } @{ $hash->{data} };
    OR
    for my $state ( @{ $hash->{data} } ) { print $state->{State} if $state->{ID} == 32; }

    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me
      print map { $_->{State} if $_->{ID} == 32 } @{ $hash->{data} };

      ccfc1986: Be aware that the processing of this data flow is IMHO problematic. For every element processed that does not match the desired ID, an extraneous empty string is returned (the  '' pairs in the example below), the result of the false evaluation | evaluation as false of the  if conditional expression. I think NetWallah's use of grep is preferable.

      c:\@Work\Perl\monks>perl -wMstrict -le "my $hash = { 'data' => [ { 'ID' => 32, 'State' => 'Stopped' }, { 'ID' => 33, 'State' => 'Stopped' }, { 'ID' => 31, 'State' => 'Running' }, ], }; ;; my @ra = map { $_->{State} if $_->{ID} == 32 } @{ $hash->{data} }; printf qq{'$_' } for @ra; " 'Stopped' '' ''

        You make a good point. Writing the map like this removes those empty strings from the result:

        map { $_->{ID} == 32 ? $_->{State} : () }

        -- Ken

Re: accessing data in hash
by NetWallah (Canon) on Mar 29, 2014 at 06:00 UTC
    A slight variation on 2teez(++) , since you want to do comparisons after finding the item:
    my ($item) = grep { $_->{ID} == 32 } @{ $hash->{data} }; # Assumes ID + is unique die "No item had ID 32" unless $item; # Now compare Item's state.. if ($item->{State} eq "Stopped"){ print "Oh - I did not expect this\n"; }
    FYI - you have a hash containing an array of hashes.

            What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their heads against?
                  -Larry Wall, 1992

      print map { $_->{State} if $_->{ID} == 32 } @{ $hash->{data} };

      ccfc1986: Be aware that the processing of this data flow is IMHO problematic. For every element processed that does not match the desired  ID an extraneous empty string is returned (the  '' pairs in the example below), the result of the false evaluation of the  if conditional expression. I think NetWallah's use of grep is preferable.

      c:\@Work\Perl\monks>perl -wMstrict -le "my $hash = { 'data' => [ { 'ID' => 32, 'State' => 'Stopped' }, { 'ID' => 33, 'State' => 'Stopped' }, { 'ID' => 31, 'State' => 'Running' }, ], }; ;; my @ra = map { $_->{State} if $_->{ID} == 32 } @{ $hash->{data} }; printf qq{'$_' } for @ra; " 'Stopped' '' ''
Re: accessing data in hash
by Laurent_R (Canon) on Mar 29, 2014 at 12:37 UTC
    As a side note to the other answers you received, there may be very good reasons elsewhere in your code to use a hash of arrays of hashes, but for what you are trying to do here, it would seem better to use a hash of hashes of hashes (because you would not need to scan the full inner array to find the required information but could access immediately to the relevant piece of data). Or possibly using a simpler data structure such as a hash of hashes (or perhaps even a simple hash).

    This assumes that the IDs are unique, but, given the context, I tend to think it must be the case, since it would probably not make much sense to have the same ID being both "Stopped" and "Started".

Re: accessing data in hash
by ccfc1986 (Initiate) on Mar 29, 2014 at 15:16 UTC
    Thank you very much to all for their comments/posts. I will take the time to read the posted links on a complex data structures in perl (including the posting guidelines). To give a little more clarity - basically prior to this output, i make an API call via a JSON - which returns the complex structure in my previous post. The structure contains a listing of services/applications running on the server - giving JobID, JobName, and running status (on/off). The reason for the call is to check if a service is stopped, if so, i can proceed with my next step in my script. I appreciate all of the responses. I will give it a go with your suggestions and see how i fare. If i come across further issues i will let you know, posting per the guidelines. Thanks again.