G'day aturtle,

In order to get a better idea of how to write your code, perhaps the first thing to do would be to take a look at the general layout of your complete data structure (which is a hashref assigned to $form).

{ id => integer, cleared => boolean, PR => [ { ... }, ... { ... }, ], }

Now that the structure is clear, you should be able to see how misleading the first line of your outer loop is:

foreach my $key ( @{ $form->{PR} } ) {

Each of the elements in @{ $form->{PR} } are hashrefs, not keys.

You attempt to clarify this (by writing unnecessary code) with my %elem = %{$key}; however, you've possibly confused yourself even more because right below this you assign an actual key to another misleadingly named variable ($var) and then make the mistake of using it as a hashref (i.e. $var->{id}):

foreach my $var ( keys %elem ) { if ($var->{id} == $form->{"id"}){

A logical indentation of your code would make it easier to both read and maintain. I didn't find it easy to understand without close study (which shouldn't be necessary for fairly straightforward code such as this). This poor layout may well have been a contributing factor in some of the errors you've made. You can get some hints and tips on how to improve this from "perlstyle - Perl style guide"; you can use perltidy to reformat your code to your chosen style.

I'd also recommend you read UNIVERSAL. In the SYNOPSIS, you'll see "but never do this!" followed by examples similar to usages in your code. The ref function would have been a better choice here; also see the reftype function in the built-in Scalar::Util module.

Here's an example of how I might have searched through your data structure and made conditional changes to it:

#!/usr/bin/env perl -l use strict; use warnings; use Data::Dumper; my $form = { id => 12594, cleared => 1, PR => [ { id => 10368, cleared => 0 }, { id => 12594, cleared => 0 }, ], }; print '*** BEFORE ***'; print Dumper $form; for my $hash_ref (@{$form->{PR}}) { if ($hash_ref->{id} == $form->{id}) { $hash_ref->{cleared} = $form->{cleared}; } } print '*** AFTER ***'; print Dumper $form;

Output:

*** BEFORE *** $VAR1 = { 'cleared' => 1, 'id' => 12594, 'PR' => [ { 'cleared' => 0, 'id' => 10368 }, { 'cleared' => 0, 'id' => 12594 } ] }; *** AFTER *** $VAR1 = { 'cleared' => 1, 'id' => 12594, 'PR' => [ { 'cleared' => 0, 'id' => 10368 }, { 'cleared' => 1, 'id' => 12594 } ] };

[Also consider using Data::Dump. In many instances, it's a better choice than Data::Dumper.]

-- Ken


In reply to Re: how to loop each anonymous hash in an array of hashes by kcott
in thread how to loop each anonymous hash in an array of hashes by aturtle

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.