Can't use string as an ARRAY ref while "strict refs" - arrays

I'm trying to dereference an array that is a value hash of a list element that is within an array so that I can manipulate and store it.
A sample of code is:
use strict;
use warnings;
my #array = qw(one two three four);
my #objects;
$objects[0]{"name"}="somestring";
$objects[0]{"value"}=#array;
print $objects[0]{"name"} . ": " . $objects[0]{"value"}[0];
print "\n";
When I try and run, I get:
Can't use string ("4") as an ARRAY ref while "strict refs" in use at
listarray.pl line 11.
Is there a way to do what I am intending (and use a foreach to iterate the inner and outer array)?

You should store the array as a reference:
$objects[0]{"value"} = \#array;
In your code, the #array was evaluated in scalar context, which returns the number of elements in the array (4).

Related

Replicate the array number of times in Perl

I have array which contains 5 elements (1,2,3,4,5). I want to replicate this a number of times based on the value set in the scalar $no_of_replication, e.g. 3.
So that my final array would contain (1,2,3,4,5,1,2,3,4,5,1,2,3,4,5).
Here is what I have tried. It gives me scalar content instead of elements.
use strict;
use warnings;
use Data::Dumper;
my #array = (1,2,3,4,5);
print Dumper(\#array);
my $no_of_replication = 3;
my #new_array = #array * $no_of_replication;
print Dumper(\#new_array);
My array(#new_array) should be like (1,2,3,4,5,1,2,3,4,5,1,2,3,4,5).
The operator for that is x and you need to be careful with the array syntax:
#new_array = ( #array ) x $no_of_replication;
Found the solution here:
Multiplying strings and lists in perl via Archive.org

How to access Array Item With Variable perl?

I'm new to perl.
I'm facing a problem to access items in array by variable like other languages eg. C C++ Python3 JavaScript
Expected Way To Do Same In Perl:
print "#array[$var]" ;
It should print value of array at $var.
But It Gives Error. Any other way To do same.
To access the value of an element of array #array, one uses $array[$i].
This is documented in perldata.
And yes, $array[$i] can be used in double-quoted string literals.
print("$array[$i]\n");
Note that #array[$i] also works, but with a warning. You should only use #array[...] when there's the possibility of getting multiple elements.
$ perl -e'
use strict;
use warnings;
my #array = "a".."z";
my $var = 2;
print "#array[$var]\n";
'
Scalar value #array[...] better written as $array[...] at -e line 7.
c
$ perl -e'
use strict;
use warnings;
my #array = "a".."z";
print "#array[2..4]\n";
'
c d e
Try this: $array[$var]. What you wrote before was an incorrect way to access an array slice. If you need a slice, try this: #array[$foo..$bar].

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

Perl: Dereferencing Array

Why does the following code not work in getting into an anonymous array?
my #d = [3,5,7];
print $(#{$d[0]}[0]);
# but print $d[0][0] works.
Script 1 (original)
Because it is invalid Perl code?
#!/usr/bin/env perl
use strict;
use warnings;
my #d = [3,5,7];
print $(#{$d[0]}[0]);
When compiled (perl -c) with Perl 5.14.1, it yields:
Array found where operator expected at xx.pl line 6, at end of line
(Missing operator before ?)
syntax error at xx.pl line 6, near "])"
xx.pl had compilation errors.
Frankly, I'm not sure why you expected it to work. I can't make head or tail of what you were trying to do.
The alternative:
print $d[0][0];
works fine because d is an array containing a single array ref. Thus $d[0] is the array (3, 5, 7) (note parentheses instead of square brackets), so $d[0][0] is the zeroth element of the array, which is the 3.
Script 2
This modification of your code prints 3 and 6:
#!/usr/bin/env perl
use strict;
use warnings;
my #d = ( [3,5,7], [4,6,8] );
print $d[0][0], "\n";
print $d[1][1], "\n";
Question
So the $ in $d[0] indicates that [3,5,7] is dereferenced to the array (3,5,7), or what does the $ do here? I thought the $ was to indicate that a scalar was getting printed out?
Roughly speaking, a reference is a scalar, but a special sort of scalar.
If you do print "$d[0]\n"; you get output something like ARRAY(0x100802eb8), indicating it is a reference to an array. The second subscript could also be written as $d[0]->[0] to indicate that there's another level of dereferencing going on. You could also write print #{$d[0]}, "\n"; to print out all the elements in the array.
Script 3
#!/usr/bin/env perl
use strict;
use warnings;
$, = ", ";
my #d = ( [3,5,7], [4,6,8] );
#print $(#{$d[0]}[0]);
print #d, "\n";
print $d[0], "\n";
print #{$d[0]}, "\n";
print #{$d[1]}, "\n";
print $d[0][0], "\n";
print $d[1][1], "\n";
print $d[0]->[0], "\n";
print $d[1]->[1], "\n";
Output
ARRAY(0x100802eb8), ARRAY(0x100826d18),
ARRAY(0x100802eb8),
3, 5, 7,
4, 6, 8,
3,
6,
3,
6,
I think you are trying for this:
${$d[0]}[0]
Though of course there's always the syntactic sugar way, too:
$d[0]->[0]
The square bracket constructor creates an anonymous array, but you are storing it in another array. This means that you are storing the three element array inside the first element of a one element array. This is why $d[0][0] will return the value 3. To do a single level array use the list constructor:
my #d = (3,5,7);
print $d[0];
If you really mean to create the array inside the outer array then you should dereference the single (scalar) value as
print ${$d[0]}[0].
For more read perldoc perlreftut.

How to retrieve an array from a hash that has been passed to a subroutine in perl

I am trying to write a subroutine that takes in a hash of arrays as an argument. However, when I try to retrieve one of the arrays, I seem to get the size of the array instead of the array itself.
my(%hash) = ( );
$hash{"aaa"} = ["blue", 1];
_subfoo("test", %hash);
sub _subfoo {
my($test ,%aa) = #_;
foreach my $name (keys %aa) {
my #array = #{$aa{$name}};
print $name. " is ". #array ."\n";
}
}
This returns 2 instead of (blue, 1) as I expected. Is there some other way to handle arrays in hashes when in a subroutine?
Apologies if this is too simple for stack overflow, first time poster, and new to programming.
You're putting your #array array into a scalar context right here:
print $name. " is ". #array ."\n";
An array in scalar context gives you the number of elements in the array and #array happens to have 2 elements. Try one of these instead:
print $name . " is " . join(', ', #array) . "\n";
print $name, " is ", #array, "\n";
print "$name is #array\n";
and you'll see the elements of your #array. Using join lets you paste the elements together as you please; the second one evaluates #array in list context and will mash the values together without separating them; the third interpolates #array by joining its elements together with $" (which is a single space by default).
As mu is too short has mentioned, you used the array in scalar context, and therefore it returned its length instead of its elements. I had some other pointers about your code.
Passing arguments by reference is sometimes a good idea when some of those arguments are arrays or hashes. The reason for this is that arrays and hashes are expanded into lists before being passed to the subroutine, which makes something like this impossible:
foo(#bar, #baz);
sub foo { # This will not work
my (#array1, #array2) = #_; # All the arguments will end up in #array1
...
}
This will work, however:
foo(\#bar, \#baz);
sub foo {
my ($aref1, $aref2) = #_;
...
}
You may find that in your case, each is a nice function for your purposes, as it will make dereferencing the array a bit neater.
foo("test", \%hash); # note the backslash to pass by reference
sub foo {
my ($test, $aa) = #_; # note use of scalar $aa to store the reference
while (my ($key, $value) = each %$aa)) { # note dereferencing of $aa
print "$key is #$value\n"; # ...and $value
}
}

Resources