0

Let's say there's an array of hashes as shown:

@test = (
   {
      VAR1 => "1",
      VAR2 => "2",
      VAR3 => "3",
   },
   {
      VAR1 => "11",
      VAR2 => "22",
      VAR3 => "33",
   },
   {
      VAR1 => "111",
      VAR2 => "222",
      VAR3 => "333",
   },
);

And an array:

@test2 = ("4,44,444");

How would one go about adding the array as a key-value pair in the array of hashes?

Shooting for an end result that would look like:

@result = (
   {
      VAR1 => "1",
      VAR2 => "2",
      VAR3 => "3",
      VAR4 => "4",
   },
   {
      VAR1 => "11",
      VAR2 => "22",
      VAR3 => "33",
      VAR4 => "44",
   },
   {
      VAR1 => "111",
      VAR2 => "222",
      VAR3 => "333",
      VAR4 => "444",
   },
);

I'm new to perl and not really sure how this could be accomplished. Thanks in advance.

1
  • 1
    Do you mean @test2 = (4, 44, 444)? As you've written it it's a one-element array. Are your hash keys really VAR1, VAR2 etc? Because if so then you need arrays and not hashes. Commented Feb 2, 2015 at 19:04

3 Answers 3

3

First of all, why is @test2 an array if all it contains is a string??? To fix that, you can use the following:

my @real_test2 = split(/,/, $test2[0]);

Why are you using hashes as arrays???? Use an AoA! If you had an AoA, it would be

for my $i (0..$#result) {
   push @{ $result[$i] }, $real_test2[$i];
}

If you want to stick with an AoH, it's very similar.

for my $i (0..$#result) {
   my $rec = $result[$i];
   my $key = 'VAR' . ( keys(%$rec) + 1 );
   $rec->{$key} = $real_test2[$i];
}

Or if you know the key is always going to be the same, you could optimize a little.

if (@result) {
   my $key = 'VAR' . ( keys(%{ $result[0] }) + 1 );
   for my $rec (@result) {
      $rec->{$key} = shift(@real_test2);
   }
}
Sign up to request clarification or add additional context in comments.

Comments

1

If you really want to stick to using an array of hashes, then this will work for you.

The for loop iterates over all the indices of @test and @test2. I've used the min function from List::Util to find the last index of the shorter of the two arrays. This avoids falling off the end of one or other of the arrays in case they are different lengths.

The highest-numbered hash key is found by using a regular expression to extract the numeric part of each key, together with the max function, also from List::Util. The next key to be used is one more than this maximum, preceded by the string VAR.

I've used Data::Dump only to show the resultant data structure.

use strict;
use warnings;

use List::Util qw/ min max /;

my @test = (
  { VAR1 => 1,   VAR2 => 2,   VAR3 => 3 },
  { VAR1 => 11,  VAR2 => 22,  VAR3 => 33 },
  { VAR1 => 111, VAR2 => 222, VAR3 => 333 },
);

my @test2 = (4, 44, 444);
my $limit = min $#test, $#test2;

for my $i (0 .. $limit) {
  my $max = max map /(\d+)/, keys %{ $test[$i] };
  $test[$i]{'VAR'.++$max} = $test2[$i];
}

use Data::Dump;
dd \@test;

output

[
  { VAR1 => 1, VAR2 => 2, VAR3 => 3, VAR4 => 4 },
  { VAR1 => 11, VAR2 => 22, VAR3 => 33, VAR4 => 44 },
  { VAR1 => 111, VAR2 => 222, VAR3 => 333, VAR4 => 444 },
]

But if you want to go for an array of arrays, then it will look more like this. It's quite similar, except that I can just use push instead of calculating an index for the next element of the arrays.

use strict;
use warnings;

use List::Util qw/ min /;

my @test = (
  [ 1, 2, 3 ],
  [ 11, 22, 33 ],
  [ 111, 222, 333 ],
);

my @test2 = (4, 44, 444);
my $limit = min $#test, $#test2;

for my $i (0 .. $limit) {
  push @{ $test[$i] }, $test2[$i];
}

use Data::Dump;
dd \@test;

output

[[1 .. 4], [11, 22, 33, 44], [111, 222, 333, 444]]

Comments

0
$test[$_]{VAR4} = $test2[$_] foreach 0..$#test2;

I have to agree with ikegami that its a very bad use of hashes.

The key to a hash should not be numerically significant—or significant of order. It should be mnemonically significant. It should tell you what the 4 is.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.