in reply to Add new data to array

From your code, I can guess that $data is a reference to an array of hashes. You wish to add four new keys to each of these hashes. The values corresponding to these keys comes from one of these hashes. The source hash is the one with a status of 'houses'.
use strict; use warnings; use Data::Dumper; my $data = [ { Ad1 => '20 SOUTH CENTRAL #B3', status => 'Property', City => 'NY', zCode => '0002', name => 'John D' }, { Ad1 => '15 SOUTH CENTRAL #B4', status => 'Property', City => 'NY', zCode => '0002', name => 'John V' }, { Ad1 => '100 main St.', status => 'houses', City => 'BO', zCode => '0007', name => 'Mary' }, ]; my @add_ins = grep { $_->{status} eq 'houses' } @$data; my $add_in = $add_ins[0]; foreach my $row (@$data) { $row->{new_name} = $add_in->{name} // ''; $row->{new_Ad1} = $add_in->{Ad1} // ''; $row->{new_City} = $add_in->{City} // ''; $row->{new_zCode} = $add_in->{zCode} // ''; } print Dumper($data);

OUTPUT:

$VAR1 = [ { 'name' => 'John D', 'new_zCode' => '0007', 'new_Ad1' => '100 main St.', 'Ad1' => '20 SOUTH CENTRAL #B3', 'zCode' => '0002', 'new_City' => 'BO', 'new_name' => 'Mary', 'status' => 'Property', 'City' => 'NY' }, { 'new_Ad1' => '100 main St.', 'Ad1' => '15 SOUTH CENTRAL #B4', 'name' => 'John V', 'new_zCode' => '0007', 'new_name' => 'Mary', 'new_City' => 'BO', 'status' => 'Property', 'City' => 'NY', 'zCode' => '0002' }, { 'new_Ad1' => '100 main St.', 'Ad1' => '100 main St.', 'name' => 'Mary', 'new_zCode' => '0007', 'new_City' => 'BO', 'new_name' => 'Mary', 'City' => 'BO', 'status' => 'houses', 'zCode' => '0007' } ];
Bill

Replies are listed 'Best First'.
Re^2: Add new data to array
by AnomalousMonk (Archbishop) on Mar 14, 2020 at 17:39 UTC

    It's possible to further simplify this (slightly) by removing the intermediate array variable:
        my ($add_in) = grep { $_->{status} eq 'houses' } @$data;
    (And I think it should be noted that the  // defined-or operator was added with Perl version 5.10.)


    Give a man a fish:  <%-{-{-{-<

      Even better way:
      use List::Util qw(first); .. my $add_in = first { $_->{status} eq 'houses' } @$data;
      Bill

        As you're making incremental improvements, here's another. Just a little Sunday morning exercise to get the mental juices flowing. :-)

        Creating the four new_* key-value pairs and doing four // checks, always produces the same result: you only need to do that once. I kept your code up to and including my $add_in = ..., then added these two statements:

        my $add_hashref = { map +('new_' . $_ => $add_in->{$_} // ''), grep $_ ne 'status', keys %$add_in }; %$_ = (%$_, %$add_hashref) for @$data;

        The Dumper output is the same as yours; at least with a fairly thorough visual check, and bearing in mind that key-value pairs are unordered in a hash.

        — Ken

Re^2: Add new data to array
by Anonymous Monk on Mar 17, 2020 at 18:24 UTC
    Why this,

    my $add_in = $add_ins[0];

    couldn't be like this?
    my $add_in = (); my @$add_in = $add_ins[0];

    Thanks!

      WRT this code, because  $add_ins[0] is a hash reference (@add_ins is an array of hash references) and so  $add_in would become (by autovivification) a reference to an array holding a single element: a hash reference. The expression  $add_in->{name} would then have to become  $add_in->[0]{name} which would be possible, but a useless complication.

      Update 1: Normally, a statement like
          my @$add_in = $add_ins[0];
      would be written
          my @$add_in = ($add_ins[0]);
      using parentheses to make the RHS a proper list, but in the special case of single-element array assignment, Perl allows the parentheses to be dispensed with. In
          my $add_in = ();
      the parentheses have no effect; the statement is equivalent to
          my $add_in;

      Update 2: BillKSmith covers a point which I neglected to mention: the statements
          my $add_in = ();
          my @$add_in = $add_ins[0];
      are syntactically incorrect due to the use of the my declarator in the second statement. However, if this operator is removed, what's left is code that can be made to compile and to run without warnings and to work, albeit IMHO in an ugly, confusing and inefficient manner as discussed above.

      c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my @add_ins = ({ qw(foo bar) }, { qw(biz boz) }); ;; my $add_in = (); @$add_in = $add_ins[0]; dd $add_in; print $add_in->[0]{'foo'} " [{ foo => "bar" }] bar


      Give a man a fish:  <%-{-{-{-<

      I do not understand what you mean. Your code is not valid Perl.
      >type tryit.pl use strict; use warnings; my $add_in = (); my @$add_in = $add_ins[0]; >perl tryit.pl "my" variable $add_in masks earlier declaration in same scope at tryit +.pl line 4 . Can't declare array dereference in "my" at tryit.pl line 4, near "$add +_in =" Global symbol "@add_ins" requires explicit package name (did you forge +t to decla re "my @add_ins"?) at tryit.pl line 4. Execution of tryit.pl aborted due to compilation errors.

      I defined the array @add_ins to force grep to run in list context. Execution of grep returnes a list (which contained only one element) and assigned it to @add_ins. The statement my $add_in = $add_ins[0]; assigns the value of that element to the scalar $add_in. Note that the value is a reference to the hash which contains the data which is to be added to every hash. AnomolousMonk accomplished the same thing by using the extra parenthesis to force list context and used list assignment to extract the single reference.

      Bill