Hameed
Hameed

Reputation: 2277

Using map on array of hashes

I have the following structure:

my @fields = (
    {
        "dbId"        => "BabysSex",
        "db2Id"       => "DetSex",
        "name"        => "Baby's Sex",
        "datatype"    => "Text",
        "outputorder" => 5,
        "value" => undef,
    },
    {
        "dbId"     => "HospitalCode",
        "name"     => "Hospital Code",
        "datatype" => "Text",
        "value" => undef,
    },
    {
        "dbId"        => "UniqueIdenifier",
        "name"        => "Unique Identifier",
        "datatype"    => "Text",
        "outputorder" => 7,
        "value" => undef,
    },

);

After assigning the values to each $filed[$i]->{"value"}, I need to do some further processing and expansion. For instance, the data set I am processing uses digits to represent different values for sex (eg 1 for male, 2 for female and so on). I can expand this in a for loop:

for ( my $i = 0 ; $i < scalar @fields ; $i++ ) {
   if ( $fields[$i]->{"name"} =~ /sex/i && $fields[$i]->{"value"} )
   {
      $fields[$i]->{"value"} = $SexMap{ $fields[$i]->{"value"}};
   }
}

What I would like to know is if I can use map to get the same results.

Thanks

Upvotes: 1

Views: 3220

Answers (1)

hobbs
hobbs

Reputation: 240809

You can, yes, but I'm not convinced that it would be right, and it's definitely not necessary.

I would begin by rewriting your code as

for (@fields) {
    $_->{value} = $SexMap{ $_->{value} } if $_->{name} =~ /sex/i and $_->{value};
}

Which works just fine because a foreach aliases $_ to each element in the array.

It could be turned into a map like

@fields = map {
    $_->{value} = $SexMap{ $_->{value} } if $_->{name} =~ /sex/i and $_->{value};
    $_;
} @fields;

but you'll notice that the map isn't actually doing anything here, it's just adding code.

If the reason that you want a map is to create a copy without modifying the original, then

@newfields = map {
    ($_->{name} =~ /sex/i and $_->{value})
    ? ( { %$_, value => $SexMap{ $_->{value} } } )
    : ( { %$_ } )
} @fields;

which does a shallow copy of each element (and therefore the map actually accomplishes something) but there are probably cleaner ways to accomplish that.

Upvotes: 4

Related Questions