Hash key is storing only the last element of loop - arrays

I am trying to store the array values in the hash, but the hash key is storing only the last value of array in the for loop.
My expected output is, 'STORE' key should have all the array elements.
I knew there are few other ways to store the array values in the hash, but I curious why the below script doesn't work.
use strict;
use warnings;
use Data::Dumper;
my #array = (1,2,3);
my %record;
for my $array(#array) {
$record{"STORE"} = $array;
}
print Dumper \%record;

The hash has only the last value from the array because you keep overwriting the value in the for loop.
One way to store all values from the array is:
use strict;
use warnings;
use Data::Dumper;
my #array = (1,2,3);
my %record;
for my $array (#array) {
push #{ $record{"STORE"} }, $array;
}
print Dumper \%record;
This stores the array as a reference.
$VAR1 = {
'STORE' => [
1,
2,
3
]
};
Another way to store the whole array is to assign it to an array reference:
my #array = (1,2,3);
my %record;
$record{"STORE"} = [#array];
print Dumper \%record;
Refer to perldsc

Related

Can array be value of Hash in Perl [duplicate]

This question already has answers here:
Unable to store array as a hash value
(2 answers)
Closed 6 years ago.
Now I need to get {"teams":[1, 2, 35]}, I wrote below code.
use JSON
my #array;
#array=(1, 2, 35);
my %hash;
$hash{"teams"}=#array;
$json = encode_json(\%hash);
print $json."\n";
but I just get {"teams":3}.
My question is can array be value of Hash in Perl?
Yes, it can.
In perl multi-dimensional structures are done via references:
#!/usr/bin/env perl
use strict;
use warnings;
use JSON;
my #array;
#array=(1, 2, 35);
my %hash;
$hash{"teams"}=\#array;
my $json = encode_json(\%hash);
print $json."\n";
The way this works is - your hash value can only be single scalar value. This should be a reference to an array.
This prints:
{"teams":[1,2,35]}
You could accomplish the same result with:
$hash{"teams"}=[#array];
Which is similar, in that it copies #array into an anonymous array.
The distinction comes if you re-use #array:
#!/usr/bin/env perl
use strict;
use warnings;
use JSON;
my #array;
#array=(1, 2, 35);
my %hash;
$hash{"teams"}=\#array;
#array = ( 3, 4, 5 ) ;
$hash{"more"} = \#array;
my $json = encode_json(\%hash);
print $json."\n";
This will actually print:
{"teams":[3,4,5],"more":[3,4,5]}
Because you've altered the array, and used a reference to the same array twice.
But if you do:
#!/usr/bin/env perl
use strict;
use warnings;
use JSON;
my #array;
#array=(1, 2, 35);
my %hash;
$hash{"teams"}=[#array];
#array = ( 3, 4, 5 ) ;
$hash{"more"} = [#array];
my $json = encode_json(\%hash);
print $json."\n";
You get:
{"more":[3,4,5],"teams":[1,2,35]}
You can see what's going on with the rather handy Data::Dumper module:
#!/usr/bin/env perl
use strict;
use warnings;
use JSON;
use Data::Dumper;
my #array;
#array = ( 1, 2, 35 );
my %hash;
$hash{"teams"} = #array;
print Dumper \%hash;
You'll see that what's in hash is:
$VAR1 = {
'teams' => 3
};
{"teams":3}
Why you might ask? Well, because the entry in a hash can only be a scalar.
So you are accessing your array in a scalar context. And an array in a scalar context, prints it's number of elements:
print scalar #array; # prints 3
Which is what's happening in your example.

remove original element from an array without removing its duplicates in perl

I have an array with duplicate elements. I would like to remove one element at a time without iterating in a loop. Also, if I remove an element, if any duplicate element exists for that element it should remain in the array. Is there any way to do this in perl?
One loop to store elements in hash, and one grep to show remaining elements. All this assuming that undef is not occurring as value in your array of duplicates.
use strict;
use warnings;
use Data::Dumper;
my #r = (1..8, 1..8);
my %ref;
push #{ $ref{$_} }, \$_ for #r;
my $to_remove = 2;
undef ${shift #{ $ref{$to_remove} }};
print Dumper \#r;
undef ${shift #{ $ref{$to_remove} }};
print Dumper \#r;
print Dumper [ grep defined, #r ];

Why does my first hash value disappear in Perl?

Why does the hash remove the first value apple:2 when I print the output?
use warnings;
use strict;
use Data::Dumper;
my #array = ("apple:2", "pie:4", "cake:2");
my %wordcount;
our $curword;
our $curnum;
foreach (#array) {
($curword, $curnum) = split(":",$_);
$wordcount{$curnum}=$curword;
}
print Dumper (\%wordcount);
Perl hash can only have unique keys, so
$wordcount{2} = "apple";
is later overwritten by
$wordcount{2} = "cake";
What you probably wanted to do was:
use warnings;
use strict;
use Data::Dumper;
my #array = ("apple:2", "pie:4", "cake:2");
my %wordcount;
for my $entry (#array) {
my ($word, $num) = split /:/, $entry;
push #{$wordcount{$num}}, $word;
}
print Dumper (\%wordcount);
This way, each entry in %wordcount relates a word count to an array of the words which appear that many times (assuming the :n in the notation indicates the count).
It is OK to be a beginner, but it is not OK to assume other people can read your mind.
Also, don't use global variables (our) when lexically scoped (my) will do.

How to pass an array as value to a single key in a hash of perl?

my %hash;
my #chain;
foreach (my $i=0; $i<=7; $i++)
{
foreach (my $j=0; $j<=($#output); $j++)
{
if ($output[$j] =~ /chain1/)
{
push (#array, $output[$j]);
}
}
$hash{$chain[$i]} = [ #array ];
}
print "$hash{$chain[0]}\n";
The problem is I am not able to assign the arrays to unique keys in the hash. when I say print all the keys print the same output.
You keep adding to the same array.
for (...) {
{
my #array; <-- Add here
for (...) {
...
push #array, $output[$j];
...
}
$hash{$chain[$i]} = \#array; <-- No need to copy elements anymore.
}
Perl hash are designed to hold only scalar values. It can have a key and the value can be the address reference of the array (which is scalar). But if the array value need to be modified concatenate the contents of the array as a string with certain delimiter and store the string as key.
Hope this Helps.

Check words and synonyms

I have an array with some words, and another array with words and synonyms. I'd like to create a third array when I find a matchin word between first and second array. I tried with grep but I'm not able to write the code in a proper way in order to get what I want.
The problem is that elements in array 1 can be found in array 2 at the beginning but also at the end or in the middle.
Maybe it's easier with an exemple:
#array1 = qw(chose, abstraction);
#array2 = (
"inspirer respirer",
"incapable",
"abstraction",
"abaxial",
"cause,chose,objet",
"ventral",
"chose,objet"
);
The result it should be
#array3 = ("abstraction", "cause,chose,objet", "chose,objet");
Is it right to use "grep"?
I'm not able to write a right syntax to solve the problem..
Thank you
You can construct a regular expression from the array1, then filter the array2 using it:
#!/usr/bin/perl
use warnings;
use strict;
my #array1 = qw(chose, abstraction);
my #array2 = (
"inspirer respirer",
"incapable",
"abstraction",
"abaxial",
"cause,chose,objet",
"ventral",
"chose,objet"
);
my $regex = join '|', map quotemeta $_, #array1; # quotemeta needed for special characters.
$regex = qr/$regex/;
my #array3 = grep /$regex/, #array2;
print "$_\n" for #array3;
I know you have an answer but here is a fun way I thought of.
So, I guess it is like an inverted index.
You take each set of synonyms and make them into an array. Then take each element of that array and put it into a hash as the keys with the value being a reference to the array.
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my #array1 = qw(chose abstraction);
my #array2 = ("inspirer respirer",
"incapable",
"abstraction",
"abaxial",
"cause,chose,objet",
"ventral",
"chose,objet"
);
my #array;
push #array, map { /,|\s/ ? [split(/,|\s/, $_)]:[$_] } #array2;
my %construct;
while(my $array_ref = shift(#array)){
for(#{ $array_ref }){
push #{ $construct{$_} }, $array_ref;
}
}
my #array3 = map { s/,//; (#{ $construct{$_} }) } #array1;
print join(', ', #{ $_ }), "\n" for (#array3);
EDIT:
Missed apart of the answer before, this one should be complete.

Resources