2

Given the following anonymous array of hashes:

$AoH = [
    {    
         'FORM_FIELD_ID'        => '10353',
         'VISIBLE_BY'           => '10354',
         'FIELD_LABEL'          => 'ISINCIDENT',
         'VALUE'                => '',
         'DEFAULT_FIELD_LABEL'  => 'Yes No',
         'FORM_ID'              => '2113',
    },
    {
         'FORM_FIELD_ID'        => '10354',
         'VISIBLE_BY'           => '0',
         'FIELD_LABEL'          => 'CATEGORY',
         'VALUE'                => 'zOS Logical Security (RACF)',
         'DEFAULT_FIELD_LABEL'  => 'CATEGORY',
         'FORM_ID'              => '2113',
    },
    {
         'FORM_FIELD_ID'        => '10368',
         'VISIBLE_BY'           => '10354',
         'FIELD_LABEL'          => 'STARTDATE',
         'VALUE'                => '',
         'DEFAULT_FIELD_LABEL'  => 'REQTYPE',
         'FORM_ID'              => '2113',

    }
];

How would I directly access the FIELD_LABEL value given that I knew the FORM_FIELD_ID is 10353?

I know I can loop through @$AoH and conditionally find $_->{FIELD_LABEL} based on $_->{FORM_FIELD_ID} == 10353, but is there anyway to directly access the wanted value if one of the other values in the same hash is known?

G. Cito
  • 6,210
  • 3
  • 29
  • 42
Namuna
  • 1,030
  • 8
  • 16
  • 2
    If you want direct lookup, you need to remap your FORM_FIELD_ID to a hash key instead. – TLP Jul 08 '13 at 19:10
  • Oh my! Satori like insight ... in the [`Devel::REPL`](https://metacpan.org/module/Devel::REPL), using `dd @$AoH` then remapping with `my %by_form_field_id = map { $_->{FORM_FIELD_ID} => $_ } @$AoH;` then `dd %by_form_field_id` visually demonstrates where the speed would come from. +1 TLP and amon. – G. Cito Jul 08 '13 at 20:37
  • A good basic and helpful question. TLP's comment and @amon's answer make it useful for learning about making simple things faster. (Changed tag) – G. Cito Mar 09 '15 at 20:13

2 Answers2

4

No, not unless you change your data structure. You could e.g. index the records by their form field id:

my %by_form_field_id = map { $_->{FORM_FIELD_ID} => $_ } @$AoH;

Then:

my $field_label = $by_form_field_id{10353}{FIELD_LABEL};

Without changing the data structure, you really have to grep:

my $field_label = (grep { $_->{FORM_FIELD_ID} == 10353 } @$AoH)[0]->{FIELD_LABEL};
amon
  • 57,091
  • 2
  • 89
  • 149
  • if your `@AoH` is more than trivial in size indexing the array from a hash element like this would be best. +1 for amon who makes it look easy. @amon ... you are making a %HoH's so the "->" is optional and `by_form_field_id{10353}{FIELD_LABEL}` looks really clean and simple. Is it more perlish to use this data structure approach or would writing a custom search function to use `grep` count as acceptable in TIMTOWTDI sense? – G. Cito Jul 08 '13 at 20:04
  • 1
    @G.Cito Creating the lookup hash is an *O(n)* operation, as is `grep`ping. If I have to perform multiple lookups, I'd create the hash, as each lookup runs in *O(1)*. I.e. for *m* lookups (*m > 1*), using a hash is *m* times as fast as `grep`. For a single lookup, `grep` is faster. I don't care about Tim Toady, as long as the right tool for the job is used. – amon Jul 08 '13 at 20:17
  • amon, Thanks for that response. I still think I'm operating on the script and small tools side of the perl universe since the grep "shellism" (admittedly a perl function of course) is what first occurred to me. I haven't quite reached the stage where I naturally grok modifying data structures to be computationally efficient. I enjoy posts that help me on this path. Cheers – G. Cito Jul 08 '13 at 20:30
0

You'd have to write a function loop through @array and examine the %hash or maybe use the builtin grep method:

say $_->{FIELD_LABEL} for (grep { $_->{FORM_FIELD_ID} == 10353 } @$AoH )

works. And so does this:

say %$_->{FIELD_LABEL} for (grep { $_->{FORM_FIELD_ID} == 10353 } @$AoH ) 

but it gives a Using a hash as a reference is deprecated warning (with pumpkin perl-5.16.3).

G. Cito
  • 6,210
  • 3
  • 29
  • 42