shift an array from the values passed to subroutine in Perl - arrays

I am passing some undefined no. of arrays to the subroutine in perl I want to get these individual arrays in the subroutine and so I can run loop.
But as i was unable so I tried passing the count of arrays. But as we can remove individual elements from an array using shift can we do same with array i.e. is there some function similar to Shift for array.
sub iFrame
{
my $count=shift #_;
for (my $i=1;$i<=$count;$i++)
{
my #iFrame =#_; #need to remove this #iFrame each time
print qq[<iframe src="$iFrame[0]" width="$iFrame[1]"
height="$iFrame[2]" frameborder="$iFrame[3]" name="$iFrame[4]"></iframe>];
# and some other code
}
A better solution would be if I am able to do the same without passing the $count of arrays.

Best way is to pass a reference to the array, then dereference it in the subroutine. Like this:
use strict;
my #array = qw(a b c);
mysub(\#array);
sub mysub
{
my #array = #{$_[0]};
foreach (#array)
{
print $_
}
}

Pass them as references.
sub iFrame
{
for my $iFrame (#_)
{
print qq[<iframe src="$iFrame->[0]" width="$iFrame->[1]"
height="$iFrame->[2]" frameborder="$iFrame->[3]" name="$iFrame->[4]"></iframe>];
# and some other code
}
}
iFrame(
[ $src1, $width1, $height1, $frameborder1, $name1 ],
[ $src2, $width2, $height2, $frameborder2, $name2 ],
);

Related

difference between the following two codes of [ and ( in perl?

When I want to assign input file to array, I am getting this error.
while (<>) {
my #tmp = split;
push my #arr,[#tmp];
print "#arr\n";
}
output: ARRAY(0x7f0b00)
ARRAY(0x7fb2f0)
If I change [ to ( then I am getting the required output.
while (<>) {
my #tmp = split;
push my #arr,(#tmp);
print "#arr\n";
output: hello, testing the perl
check the arrays.
What is the deference between (#tmp) and [#tmp]?
Normal parentheses () have no special function besides changing precedence. They are commonly used to confine a list, e.g. my #arr = (1,2,3) Square brackets return an array reference. In your case, you would be constructing a two-dimensional array. (You would, if your code was not broken).
Your code should perhaps be written like this. Note that you need to declare the array outside the loop block, otherwise it will not keep values from previous iterations. Note also that you do not need to use a #tmp array, you can simply put the split inside the push.
my #arr; # declare #arr outside the loop block
while (<>) {
push #arr, [ split ]; # stores array reference in #arr
}
for my $aref (#arr) {
print "#$aref"; # print your values
}
This array would have the structure:
$arr[0] = [ "hello,", "testing", "the", "perl" ];
$arr[1] = [ "check", "the", "arrays." ];
This is a good idea if you for example want to keep lines of input from being mixed up. Otherwise all values end up in the same level of the array.

How to modify array elements using subroutine in Perl

I am trying to modify an array passed to a subroutine.
I am passing an array reference to the subroutine and assigning new values but it is not getting reflected in the caller side.
Below is my program.
sub receiveArray {
my $arrayref = #_;
#{$arrayref} = ( 4, 5, 6 );
}
#ar = ( 1, 2, 3 );
print "Values of the function before calling the function\n";
foreach my $var ( #ar ) {
print $var;
print "\n";
}
receiveArray(\#ar);
print "Values of the function after calling the function\n";
foreach my $var ( #ar ) {
print $var;
print "\n";
}
What is the problem in the above code?
You should start every Perl file you write with use strict; use warnings;. That will help you avoid errors like this.
The problem is in this line:
my $arrayref = #_;
You're assigning an array to a scalar, so the array is evaluated in scalar context, which yields the number of elements in the array.
What you should do instead is:
my ($arrayref) = #_;
Now it's using list assignment, putting the first function argument into $arrayref (and ignoring the rest, if any).
List assignment is documented in perldoc perldata (the part starting with "Lists may be assigned to ...").

Passing an Array of an Array to a subroutine using perl

Ok, so I got an array of an array (AoA) and I need to pass it to a subroutine, and then access it. This works… but is it strictly correct and indeed is there a better way that I should be doing this?
#!/usr/bin/perl
$a = "deep";
push(#b,$a);
push(#c,\#b);
print "c = #{$c[0]}\n";
&test(\#c);
sub test
{
$d = $_[0];
print "sub c = #{$$d[0]}\n";
}
Thanks
The definitely better way to do it is to use strict; and use warnings; and to declare your variables before using them.
Also, you know that is not good practice to name your vars a or b - give them meaningful names, especially because the $a variable for example, is defined by the compiler (the one used with sort {} #).
use strict; # Always!
use warnings; # Always!
sub test {
my ($d) = #_;
print "$d->[0][0]\n";
# Or to print all the deep elements.
for my $d2 (#$d) {
for (#$d2) {
print "$_\n";
}
}
}
{
my $a = "deep"; # or: my #c = [ [ "deep" ] ];
my #b;
my #c;
push(#b,$a);
push(#c,\#b);
test(\#c); # Can't pass arrays per say, just refs. You had this right.
}
Still needs better names. In particular, $a and $b should be avoided as they can interfere with sort.

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
}
}

How can I extract an array from a two-dimensional array in Perl?

I have once again forgotten how to get $_ to represent an array when it is in a loop of a two dimensional array.
foreach(#TWO_DIM_ARRAY){
my #ARRAY = $_;
}
That's the intention, but that doesn't work. What's the correct way to do this?
The line my #ARRAY = #$_; (instead of = $_;) is what you're looking for, but unless you explicitly want to make a copy of the referenced array, I would use #$_ directly.
Well, actually I wouldn't use $_ at all, especially since you're likely to want to iterate through #$_, and then you use implicit $_ in the inner loop too, and then you could have a mess figuring out which $_ is which, or if that's even legal. Which may have been why you were copying into #ARRAY in the first place.
Anyway, here's what I would do:
for my $array_ref (#TWO_DIM_ARRAY) {
# You can iterate through the array:
for my $element (#$array_ref) {
# do whatever to $element
}
# Or you can access the array directly using arrow notation:
$array_ref->[0] = 1;
}
for (#TWO_DIM_ARRAY) {
my #arr = #$_;
}
The $_ will be array references (not arrays), so you need to dereference it as:
my #ARRAY = #$_;

Resources