Perl for loop error - arrays

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.

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

Extract number from array in Perl

I have a array which have certain elements. Each element have two char "BC" followed by a number
e.g - "BC6"
I want to extract the number which is present and store in a different array.
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);
my #band = ("BC1", "BC3");
foreach my $elem(#band)
{
my #chars = split("", $elem);
foreach my $ele (#chars) {
looks_like_number($ele) ? 'push #band_array, $ele' : '';
}
}
After execution #band_array should contain (1,3)
Can someone please tell what I'm doing wrong? I am new to perl and still learning
To do this with a regular expression, you need a very simple pattern. /BC(\d)/ should be enough. The BC is literal. The () are a capture group. They save the match inside into a variable. The first group relates to $1 in Perl. The \d is a character group for digits. That's 0-9 (and others, but that's not relevant here).
In your program, it would look like this.
use strict;
use warnings;
use Data::Dumper;
my #band = ('BC1', 'BC2');
my #numbers;
foreach my $elem (#band) {
if ($elem =~ m/BC(\d)/) {
push #numbers, $1;
}
}
print Dumper #numbers;
This program prints:
$VAR1 = '1';
$VAR2 = '2';
Note that your code had several syntax errors. The main one is that you were using #band = [ ... ], which gives you an array that contains one array reference. But your program assumed there were strings in that array.
Just incase your naming contains characters other than BC this will exctract all numeric values from your list.
use strict;
use warnings;
my #band = ("AB1", "BC2", "CD3");
foreach my $str(#band) {
$str =~ s/[^0-9]//g;
print $str;
}
First, your array is an anonymous array reference; use () for a regular array.
Then, i would use grep to filter out the values into a new array
use strict;
use warnings;
my #band = ("BC1", "BC3");
my #band_array = grep {s/BC(\d+)/$1/} #band;
$"=" , "; # make printing of array nicer
print "#band_array\n"; # print array
grep works by passing each element of an array in the code in { } , just like a sub routine. $_ for each value in the array is passed. If the code returns true then the value of $_ after the passing placed in the new array.
In this case the s/// regex returns true if a substitution is made e.g., the regex must match. Here is link for more info on grep

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.

Reverse the order of key, value in an array conversion to a hash

Suppose I have an array of values, then keys (the reverse of what an assignment to a hash would expect):
use strict;
use warnings;
use Data::Dump;
my #arr = qw(1 one 2 two 3 three 4 four 1 uno 2 dos 3 tres 4 cuatro);
my %hash = #arr;
dd \%hash;
Prints
{ 1 => "uno", 2 => "dos", 3 => "tres", 4 => "cuatro" }
Obviously, the duplicate keys are eliminated when the hash is constructed.
How can I reverse the order of the pairs of values used to construct the hash?
I know that I can write a C style loop:
for(my $i=1; $i<=$#arr; $i=$i+2){
$hash{$arr[$i]}=$arr[$i-1];
}
dd \%hash;
# { cuatro => 4, dos => 2, four => 4, one => 1, three => 3, tres => 3, two => 2, uno => 1 }
But that seems a little clumsy. I am looking for something a little more idiomatic Perl.
In Python, I would just do dict(zip(arr[1::2], arr[0::2]))
Use reverse:
my %hash = reverse #arr;
A list of the built-in functions in Perl is in perldoc perlfunc.
TLP has the right answer, but the other way to avoid eliminating dup keys is to use hash of arrays. I am assuming that's the reason for you reversing the array in the first place.
use strict;
use warnings;
use Data::Dump;
my #arr = qw(1 one 2 two 3 three 4 four 1 uno 2 dos 3 tres 4 cuatro);
my %hash;
push #{ $hash{$arr[$_]} }, $arr[$_ + 1] for grep { not $_ % 2 } 0 .. $#arr;
dd \%hash;
Output:
{
1 => ["one", "uno"],
2 => ["two", "dos"],
3 => ["three", "tres"],
4 => ["four", "cuatro"],
}
As suggested by ikegami in the comments, you can take a look at the List::Pairwise module available on CPAN for a more readable solution:
use strict;
use warnings;
use Data::Dump;
use List::Pairwise qw( mapp );
my #arr = qw(1 one 2 two 3 three 4 four 1 uno 2 dos 3 tres 4 cuatro);
my %hash;
mapp { push #{ $hash{$a} }, $b } #arr;
dd \%hash;
TLP has the right answer if your array of value, keys are ready to go into the hash.
That said, if you want to process the key or value in anyway before they go into the hash, I find this to be something I use:
while (my ($v, $k)=(shift #arr, shift #arr)) {
last unless defined $k;
# xform $k or $v in someway, like $k=~s/\s*$//; to strip trailing whitespace...
$hash{$k}=$v;
}
(Note -- destructive to the array #arr. If you want to use #arr for something else, make a copy of it first.)

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