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];
$values_hash = ( ... );? That's not how you create a hash variable...