Reputation: 35
In Perl, I have an array
my @array = (1 3 6 12);
From the above array, I want hash which is mapped from one to next value and continue.
I want this to be output like this. And the last the number should be mapped to its own
$VAR1 = {,
'1' => '3',
'3' => '6',
'6' => '12',
'12' => '12'
};
This is the code I have tried to get the hash from arrays in Perl
use strict;
use warnings;
use Data::Dumper qw(Dumper);
my @array = qw(1 3 6 12);
my %hash = @array;
print Dumper \%hash;
I get the output as:
$VAR1 = {
'6' => '12',
'1' => '3'
};
Can someone help since I am beginner in Perl ?
Thanks in advance
Upvotes: 0
Views: 182
Reputation: 2719
Step through the array and use each element as a key and the next element as the value unless you are at the last element:
foreach $x(0..$#array) {
($x == $#array) ? ($hash{$array[$x]} = $array[$x]) : ($hash{$array[$x]} = $array[$x+1]);
}
foreach $y (sort {$a<=>$b} keys %hash) {
print "$y => $hash{$y}\n";
}
Upvotes: 0
Reputation: 69264
The common way to walk an array is to use a for
loop to iterate over the elements of the array.
for (@values) {
say $_;
}
But in this case, we need each element in the array as well as the next element in the array. So it'll be more convenient to iterate over the indexes of the array. We use the special variable $#values
which gives us the final index in the array.
for (0 .. $#values) {
say "The value at index $_ is $values[$_]"
}
We can then get next element as well:
for (0 .. $#values) {
say "$values[$_] => $values[$_ + 1]"
}
Running that gets us close to the data we want:
1 => 3
3 => 6
6 => 12
Use of uninitialized value in concatenation (.) or string at array2hash line 10.
12 =>
But because 12 is the last element in the array, getting the next element makes no sense (and Perl gives us and undef
value - hence the warning).
In your example, it looks like you want the final element to point to itself. We can use the "defined-or" operator (//
) to handle that:
for (0 .. $#values) {
say "$values[$_] => ", $values[$_ + 1] // $values[$_];
}
All that remains now is to store the required data in a hash:
my %values_hash;
for (0 .. $#values) {
$values_hash{$values[$_]} = $values[$_ + 1] // $values[$_];
}
Using Data::Dumper to examine our hash, we get this:
$VAR1 = {
'3' => 6,
'12' => 12,
'6' => 12,
'1' => 3
};
Which (taking account of the fact that hashes are unordered) is what we wanted.
A Perl expert might rewrite it as:
my %values_hash = map {
$values[$_] => $values[$_ + 1] // $values[$_]
} 0 .. $#values;
Update: Another approach would be to use a hash slice.
my %values_hash;
@values_hash{@values} = @values[1 .. $#values, $#values];
Upvotes: 5
Reputation: 241868
You can assign the array directly to the hash to get half of the pairs. Use an array slice to get the other half.
my %hash = (@values, @values[1 .. $#values, $#values]);
This doesn't work for an array with an odd number of elements, but it's unclear what output you expect in such a case. Also, it's unclear what to do with repeated elements.
Upvotes: 2