Reputation: 6568
I'm trying to create a hash in which keys are contained in an array and values in an array of an array:
my @keys = (1,2,3,4,5);
my @value1 = (a,b,c,d,e);
my @value2 = (f,g,h,i,j);
my @value3 = (k,l,m,n,o);
my @values = ([@value1],[@value2],[@value3]);
my %hash;
I want to create a hash with @keys as keys, and @values as values so that key '1' would return the values a,f,k (0th element in each array) and so on.
For a single key this would be achieved as follows:
%hash=('key'=>@values);
But I'm unsure how to modify this for an array of keys.
Any help would be amazing!
Cheers,
N
Upvotes: 4
Views: 1881
Reputation: 98378
use Algorithm::Loops 'MapCarE';
my @keys = qw(1 2 3 4 5);
my @value1 = qw(a b c d e);
my @value2 = qw(f g h i j);
my @value3 = qw(k l m n o);
my %hash = MapCarE { $_[0] => [ @_[1..$#_] ] } \(@keys, @value1, @value2, @value3);
MapCarE loops through the arrays, calling the code you supply first passing the first elements of the arrays, then the seconds element, etc.
Upvotes: 0
Reputation: 1482
Try this...
#! /usr/bin/perl use strict; use warnings; use Data::Dumper; my @keys = qw( undef 0 1 $key kappa ); my @value1 = qw(a b c d e); my @value2 = qw(f g h i j); my @value3 = qw(k l m n o); # not used here... # my @values = ([@value1],[@value2],[@value3]); my %hash = map { my $key = "$keys[$_]"; $key => [ $value1[$_], $value2[$_], $value3[$_] ] } (0..$#keys); for my $key ( sort keys %hash ) { print "Key: $key contains: "; for my $value ( @{$hash{$key}} ) { print "$value "; } print "\n"; } print "Should print 'c': ".@{$hash{'1'}}[0]."\n"; print "Should print 'j': ".@{$hash{'kappa'}}[1]."\n"; # print Dumper( %hash );
With expected output like this:
Key: $key contains: d i n Key: 0 contains: b g l Key: 1 contains: c h m Key: kappa contains: e j o Key: undef contains: a f k Should print 'c': c Should print 'j': j
Adding: If you'd like to access a single value within the hash, it should be surrounded by @{} to convert the anonymous array reference, and then ended with your index (starting from zero) in square brackets, like [0]. Examples:
print "Should print 'c': ".@{$hash{'1'}}[0]."\n"; print "Should print 'j': ".@{$hash{'kappa'}}[1]."\n";
Modified to include Ekkehard's more proper usage of (0..$#..) and added some bullet proofing of the keys.
Upvotes: 2
Reputation: 107030
I take advantage of the syntax $foo[$i][$j];
to represent your array of arrays as a two dimensional array. Here's an answer sans the map
:
#! /usr/bin/env perl
use 5.12.0;
use warnings;
use Data::Dumper;
my @keys = qw(alpha beta gamma delta epsolon);
my @values1 = qw(one two three four five);
my @values2 = qw(uno dos tres quatro cinco);
my @values3 = qw(a b c d e);
my @values = ( \@values1, \@values2, \@values3 );
my %hash;
for my $item ( (0..$#keys) ) {
my @array;
push @array, $values[0][$item], $values[1][$item], $values[2][$item];
$hash{$keys[$item]} = \@array;
}
say Dumper \%hash;
Here's the output:
$VAR1 = {
'gamma' => [
'three',
'tres',
'c'
],
'delta' => [
'four',
'quatro',
'd'
],
'alpha' => [
'one',
'uno',
'a'
],
'beta' => [
'two',
'dos',
'b'
],
'epsolon' => [
'five',
'cinco',
'e'
]
};
Looks about right. Of course, I never verified that the various arrays are all the same size.
Upvotes: 2
Reputation: 3765
Something like this:
my %hash = map { $keys[$_] => [ $value1[$_], $value2[$_], $value3[$_] ] } 0..$#keys;
assuming that all four lists have the same length.
Upvotes: 4
Reputation: 38745
Combining the best of Vedran's and Jim's solutions:
use strict;
use warnings;
# my @keys = ( 1, 2, 3, 4, 5);
my @keys = ( 'alpha','beta','gamma','delta','epsilon');
my @value1 = ('a','b','c','d','e');
my @value2 = ('f','g','h','i','j');
my @value3 = ('k','l','m','n','o');
my %hash = map { $keys[$_] => [ $value1[$_], $value2[$_], $value3[$_] ] } (0 .. $#keys);
printf 'first (%s) value: [%s]', $keys[0], join ", ", @{$hash{$keys[0]}};
output:
first (alpha) value: [a, f, k]
or:
first (1) value: [a, f, k]
depending on which @keys you choose.
Upvotes: 1