Can array be value of Hash in Perl [duplicate] - arrays

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.

Related

Hash key is storing only the last element of loop

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

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.

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.

Perl for loop error

I am new to the Perl, I was trying to execute a simple program as encoded below using Strawberry perl 5, version 16:
#!usr/bin/perl
use warnings;
use strict;
my #array= {1,2,3,5,7,9};
my $i;
foreach $i (#array)
{
print qq(Element is $i\n);
}
I am getting the below as output:
Element is HASH(0x3f8b4c)
However the output that I should receive is:
Element is 1
Element is 2
Element is 3
Element is 5
Element is 7
Element is 9.
Appreciate your help in this.
To initialize an array, use a list like
my #array = (1, 2, 3, 5, 7, 9);
Note: The parens just sort out the precedence, they are not a special array syntax.
Curlies delimit an anonymous hashref, like
my $foobar = {
foo => "bar",
baz => "qux",
};
So what happened is that you assigned to your array a list of one anonymous hashref, just like
my #array = ({
1 => 2,
3 => 5,
7 => 9,
})
would have worked.
you should use () to define an array instand of {},{} is used to defind a hash
#!usr/bin/perl
use warnings;
use strict;
my #array= (1,2,3,5,7,9);
my $i;
foreach $i (#array)
{
print qq(Element is $i\n);
}
#!usr/bin/perl
use warnings;
use strict;
my #array= (1,2,3,5,7,9);
foreach my $i (#array)
{
print "Element is ", $i,"\n"; ##Or as u want..many ways to do things in perl
}
Try like this. The array should be in parenthesis. Curly braces to be used in hashes.

Sorting Arrays in Perl?

I am getting an error while trying to sort a simple array...
The ERROR reads: "use of uninitialized value in numeric comparison (<=>) at file.pl line #"
#!/usr/bin/perl
use strict
use wardings
use Data::Dumper
my #array
my $array
$array[1]= 5
$array[2]= 2
$array[3]= 3
$array[4]= 4
$array[5]= 1
sub numerically {$a <=> $b}
my #sortedarray = sort numerically #array;
print "#sortedarray\n";
I am just trying to sort the array to get:
1 2 3 4 5
I am new at perl so this might just be something stupid, but please help me... Thanks
Arrays are indexed starting at 0. The error comes from trying to sort the array when $array[0] is undefined.
Update: Also, in perl, one would write:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my #array = qw(1 2 3 4 5);
sub numerically {$a <=> $b}
my #sortedarray = sort numerically #array;
print "#sortedarray\n";
There is no point in declaring $array -- that would be a scalar. You are only working with the array #array, even though it is called with a $. Please read the perl documentation.
first of all, you need a semi-colon at the end of every statement. second, you're not using Data::Dumper, so why do you include it? You also don't need to declare the sub:
#!/usr/bin/env perl
use strict;
use warnings;
my #sorted = sort {$a <=> $b} qw (4 2 3 1 5);
print "#sorted\n";
And there we have it.
You're missing a shedload of semicolons.
It's warnings, not wardings.
Element 0 in your array is undefined.

Resources