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

Hi Monks!

I have to check if this value XXy in the hashref is true in the array, if it is
get the value of "expdate" and use it to update the hashref YYK "expdate" with it. Do a need a second loop, is that why $newdate has no value?

I am trying to get this at the end.

{ 'code' => 'YYK', 'expdate' => '2017-01-01', # <<< noticed that this value was found +in the hashref XXY 'date' => '2014-02-20', 'product' => 'buc', 'city' => 'MARS' }

My test case:
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; my $data = [ { 'code' => 'XXY', 'expdate' => '2017-01-01', 'date' => '2017-01-30', 'product' => 'cell', 'city' => 'NYK' }, { 'code' => 'YYK', 'expdate' => '2015-05-05', 'date' => '2014-02-20', 'product' => 'buc', 'city' => 'MARS' }, { 'code' => 'RX Issued', 'expdate' => '2019-11-09', 'date' => '2011-03-11', 'product' => 'idx', 'city' => 'BXO' }, ]; my $results = process( $data ); print "\n\n"; print Dumper $results; print "\n\n"; sub process { my $all = shift || return; my $setdate; my $newdate; foreach my $all_item (reverse @{ $all }) { # If XXY is found use the value in the "expdate" to replace the "e +xpdate" value in YYK # First check if XXY is true and store it if ( $all_item->{ code } eq 'XXY' ) { $newdate = $all_item->{expdate}; } if( $all_item->{ code } eq 'YYK') { # Now, set the new date $all_item->{expdate} = $newdate if $newdate; $setdate = $all_item; } } return $setdate; }

Thanks for looking!

Replies are listed 'Best First'.
Re: Replace a value with another value from the same array
by haukex (Archbishop) on May 09, 2017 at 19:30 UTC

    Are the elements in the array always in this order, i.e. XXY comes before YYK? If yes, then why don't you just remove the reverse from foreach my $all_item (reverse @{ $all })? Then it works for me.

    If the order of the data can change, then what the easiest way to solve it is depends on how big the input data can get - if it's always small, then you can just loop over the data array twice, once to get the value from XXY and once to save it to YYK.

      No, it isn't in this order and I need to use "reverse" for other proposes. The data varies in size and it can get bigger.

        Ok, here's a solution that does it on a single pass regardless of order, it takes advantage of the fact that the array elements are references to the anonymous hashes (perlreftut, perlref, perldsc):

        my ($source,$target); for my $item (@$all) { if ( $item->{code} eq 'XXY' ) { $source = $item; $target->{expdate} = $item->{expdate} if defined $target; } if ( $item->{code} eq 'YYK' ) { $target = $item; $item->{expdate} = $source->{expdate} if defined $source; } }

        I think you are going to need two passes since you imply you cannot insure the order of the array.