perl, function only printing first element of the array - perl

I have an array that has several elements on it but when I pass the array as a parameter to a function and then call the function it only prints out the first element of the array multiple times. For example
my $element;
my $random_variable = "Testing";
my #the_array = ("hello", "bye", "hey");
foreach $element(#the_array)
{
PrintFunction(#the_array, $random_variable)
}
sub PrintFunction{
my ($the_array, $random_variable) = #_;
// other code here
print $the_array . "\n";
}
The result I get from this is
hello
hello
hello
The result I want is to print all the elements of the array as
hello
bye
hey

Change:
PrintFunction(#the_array, $random_variable)
to:
PrintFunction($element, $random_variable)
Your code passes the entire array to the sub, then you only print the 1st element of the array each time because you use the scalar variable $the_array inside the sub. Since foreach grabs each element of the array, you probably meant to use $element.

Add Print #_; to your sub to see what is passed to it. You will see:
hellobyeheyTesting
hellobyeheyTesting
hellobyeheyTesting
It means you are passing the entire array followed by the $random_variable. Therefore, $the_arrayin the sub will be always the first elements of #the_array which is hello. To fix that, you should pass each element of array iteratively by
foreach $element(#the_array)
{
PrintFunction(#element, $random_variable)
}

Related

What is the proper way to dereference a multidimensional array in Perl?

In my code I have a multidimensional array
$rows[$x][$y]
I am passing it to a sub function with multiple uses but at some point that function will need to remove (pop) one of the elements from the main array.
I believe the proper way to pass it is by referencing it since I am passing more than just the array:
filterout(\#rows, $y, $data );
But am unsure of the syntax to dereferencing it on the subroutine side.
Would appreciate any help, thanks as alway.
To pop from an array reference, use
my $last = pop #$aref;
Or, in more recent Perl versions,
my $last = pop $aref->#*;
To pop the inner array, you need to dereference the given element of the array reference:
my $last = pop #{ $aref->[$index] };
or
my $last = pop $aref->[$index]->#*;
It's an array ref pointing to an array of array refs pointing to arrays of scalars. So you'll need two de-references for a single element, one for a column and none for a row:
sub filterout(\#$$) {
my($array_ref, $y, $data) = #_;
# single element <row>,<col>
$array_ref->[ <row >]->[ <column> ] = ...;
# pop column of <row>
pop(#{ $array_ref->[ <row> ] });
# pop row
pop(#{ $array_ref });
}
filterout(#rows, $y, $data);
Note the prototype, which makes filterout() work like push().

Perl find out if X is an element in an array

I don't know why small things are too not working for me in Perl. I am sorry for that.
I have been trying it around 2 hrs but i couldn't get the results.
my $technologies = 'json.jquery..,php.linux.';
my #techarray = split(',',$technologies);
#my #techarray = [
# 'json.jquery..',
# 'php.linux.'
# ];
my $search_id = 'json.jquery..';
check_val(#techarray, $search_id);
And i am doing a "if" to search the above item in array. but it is not working for me.
sub check_val{
my #techarray = shift;
my $search_id = shift;
if (grep {$_ eq $search_id} #techarray) {
print "It is there \n";
}else{
print "It is not there \n";
}
}
Output: It always going to else condition and returns "It is not there!" :(
Any idea. Am i done with any stupid mistakes?
You are using an anonymous array [ ... ] there, which as a scalar (reference) is then assigned to #techarray, as its only element. It is like #arr = 'a';. An array is defined by ( ... ).
A remedy is to either define an array, my #techarray = ( ... ), or to properly define an arrayref and then dereference when you search
my $rtecharray = [ .... ];
if (grep {$_ eq $search_id} #$rtecharray) {
# ....
}
For all kinds of list manipulations have a look at List::Util and List::MoreUtils.
Updated to changes in the question, as the sub was added
This has something else, which is more instructive.
As you pass an array to a function it is passed as a flat list of its elements. Then in the function the first shift picks up the first element,
and then the second shift picks up the second one.
Then the search is over the array with only 'json.jquery..' element, for 'php.linux.' string.
Instead, you can pass a reference,
check_val(\#techarray, $search_id);
and use it as such in the function.
Note that if you pass the array and get arguments in the function as
my (#array, $search_id) = #_; # WRONG
you are in fact getting all of #_ into #array.
See, for example, this post (passing to function) and this post (returning from function).
In general I'd recommend passing lists by reference.

Why I can't do "shift subroutine_name()" in Perl?

Why does this code return an Not an ARRAY reference error?
sub Prog {
my $var1 = 1;
my $var2 = 2;
($var1, $var2);
}
my $variable = shift &Prog;
print "$variable\n";
If I use an intermediate array, I avoid the error:
my #intermediate_array = &Prog;
my $variable = shift #intermediate_array;
print "$variable\n";
The above code now outputs "1".
The subroutine Prog returns a list of scalars. The shift function only operates on an array. Arrays and lists are not the same thing. Arrays have storage, but lists do not.
If what you want is to get the first element of the list that Prog returns, do this:
sub Prog {
return ( 'this', 'that' );
}
my $var = (Prog())[0];
print "$var\n";
I changed the sub invocation to Prog() instead of &Prog because the latter is decidedly old style.
You can also assign the first element to a scalar like others are showing:
my ($var) = Prog();
This is roughly the same as:
my ($var, $ignored_var) = Prog();
and then ignoring $ignored_var. If you want to make it clear that you're ignoring the second value without actually giving it a variable, you can do this:
my ($var, undef) = Prog();
Prog is returning a list, not an array. Operations like shift modify the array and cannot be used on lists.
You can instead do:
my ($variable) = Prog; # $variable is now 1:
# Prog is evaluated in list context
# and the results assigned to the list ($variable)
Note that you don't need the &.

Combine scalar array references in perl

I have a datastructure like:
$hashRef->{"key1"}->{"key2"} = ['1','2','3']
This $hashRef gets new values every iteration of the for loop. I am trying to append all of these to produce an output like so:
$hashRef->{"key1"}->{"key2"} = ['loop1.out1','loop1.out2','loop1.out3','loop2.out1','loop2.out2','loop2.out3',...]
loop1.ou1 is symbolic for the first output from loop 1 and not intended to be printed.
Is this possible?
Hope this is what you want:
map {
push(#{$hashRef->{"key1"}->{"key2"}}, "loop$count.out".$_);
} #{$arr2};
$count is the loop number.
#{$arr1} is the incoming array.
Thanks,
Anoop
You may use push to append new values to the array:
push( #{$hashRef->{"key1"}->{"key2"}}, 'loop1.out1','loop1.out2','loop1.out3');
$aData = [ 'loop2.out1','loop2.out2','loop2.out3' ];
push( #{$hashRef->{"key1"}->{"key2"}}, #$aData);
print join(",",#{$hashRef->{"key1"}->{"key2"}} ),"\n";

Retrieve a particular return value in Perl

I'm looking for a one-liner that lets me grab the second return value from a subroutine.
Rather than this:
($a,$b)=function;
print $b
It should be possible to do something like this
print ??? function
This works:
sub test { return (1,2) }
print ((test)[1]); # Returns 2
This also works:
print +(func())[1], "\n";
assuming that function() returns a list, then using a slice like the poster above suggested works just fine. If it returns an array reference, then you need to access it appropriately, for instance (#{function()})[1] to dereference the aref and then slice it.