Anyone know how to do this? I have been looking all day for methods on the internet, but can't find anything that seems to work.
I need to be able to evaluate the contents of two arrays and populate a third array with the return output of the subroutine, so something like this pseudo code:
sub example {
if ($arrayA[0] matches some critera && $arrayB[0] matches some criteria) {
do stuff
and populate arrayC perhaps by push(@arrayC)
other elsif/else statements
}
return @arrayC();
}
etc
Nedals
04-12-2011, 07:34 PM
So what's the problem? You almost did it already :)
my @arrayC = example(\@arrayA, \@arrayB);
sub example {
my ($aryA_ref, $aryB_ref) = @_;
my @arrayC = ();
if ($aryA->[0] eq ??? && $aryB->[0] eq ???) {
## do stuff
push @arrayC, ???
##other elsif/else statements
}
return @arrayC;
}
A_Tame_Lion
04-13-2011, 03:09 AM
Hi Nedals,
I think I understand your code, but what I don't get is the resons for the differences in references to arrays, for example - outside the subroutine:
\@arrayA
but inside the subroutine:
$aryA_ref
I can understand the usage of a scalar context but shouldn't the reference inside the subroutine be:
\$arrayA_ref
A_Tame_Lion
04-13-2011, 03:33 AM
Also using strict pragma, for some reason the use of $aryA and $aryB produces the warning "Global symbol requires explicit package name".
Sixtease
04-13-2011, 03:42 AM
@foo is an array.
\@foo is a reference to the array. This reference itself is a scalar.
$foo_ref = \@foo; we can assign the reference to a scalar variable.
sub process_arrays {
my ($array1, $array2) = @_;
# do something with the arrays
}
my @array_even = (0,2,4,6,8);
my @array_odd = (1,3,5,7,9);
# call 2
my $even_ref = \@array_even;
my $odd_ref = \@array_odd;
process_arrays($even_ref, $odd_ref);
Call 1 and call 2 are exactly the same: You pass two scalar values -- which happen to be array references -- to the subroutine. That's why in the subroutine, you reference them as $array1 and $array2, without extra backslashes.
When you want to get your hands on the array that the reference references, use @{$array1}, like this:
sub which_array_is_longer {
my ($array1, $array2) = @_;
my $length1 = scalar @{$array1};
my $length2 = scalar @{$array2};
return $length1 <=> $length2
}
You can find more about references on perlref (http://perldoc.perl.org/perlref.html).
A_Tame_Lion
04-13-2011, 04:25 AM
Hi Sixtease,
I think I'm getting there, and in fact I did find a way to get my subroutine to output a scalar, then putting that into a for loop to produce the array I wanted, prior to reading the responses on this thread, but that produced some errors later in my script.
My problem is that now my array only contains one value, when it should have 14, and did when I used my earlier method?
The subroutine is a bit of a mess, sorry. :-) I think the biggest problem may be that you modify the @avTime array in the subroutine (via pushes) and then you assign to the same array the return value from the subroutine:
my @avTime = avTime(\@time, \@tdef);
sub avTime {
...
push (@avTime, $array1->[0]);
...
}
I don't get why you are passing two arrays to the sub when all you ever seem to use are the first elements of those arrays. Or did I miss something?
I don't have the time to thoroughly analyze the function but maybe say what it's supposed to do, and we can try to look how to make it a bit nicer. ;-)
A_Tame_Lion
04-14-2011, 02:47 PM
Hi Sixtease,
I appreciate your analysis of my code, I'm not offended by your comment at all, and I can imagine how "crude" my code must look to Perl Gurus such as yourselves, but I am a beginner and I have to start somewhere;-)
I don't get why you are passing two arrays to the sub when all you ever seem to use are the first elements of those arrays. Or did I miss something?
That's it! I'm trying to evaluate all the elements in the array, How to I change the $array1->[0] to a method that will do this, is it
$_
@_
Or should I use a for loop or something and instead of using $array1->[0] use $array1->[$i]?
Nedals
04-14-2011, 06:39 PM
Also using strict pragma, for some reason the use of $aryA and $aryB produces the warning "Global symbol requires explicit package name".
That was a typo on my part
if ($aryA->[0] eq ??? && $aryB->[0] eq ???) { should have been if ($aryA_ref->[0] eq ??? && $aryB_ref->[0] eq ???)
Not sure what you are trying to do.
Are @time and @tdet arrays the same size? (I would not use @time as an array name. It will likely get confusing at a later date)
What elements of each array do you wish to evaluate, and how?
You will definately need to loop through the arrays within your sub to get the third array
my $array3_ref = avTime(\@array1, \@array2);
sub avTime {
my ($array1_ref, $array2_ref) = @_; ## Remember these are references
my @array3 = (); ## Not a reference
my $idx2 = 0; ## perhaps an index for @array2
for (@$array1_ref) { ## de-reference the $array1_ref
# now you can use $_ for the array values
if ($_ == $array2_ref->[$idx2]) { ## compare the array elements
...
push @array3, some value
}
$idx2++;
}
return \@array3;
}
A_Tame_Lion
04-17-2011, 10:44 AM
Hi Nedals,
I have been so busy I forgot to reply to say I got this to work! Everything is working perfectly now, although I have had to make a few adjustments to my code. Thanks for you and Sixtease help!
I might figure it out by the time you reply, but I am looking at slimming down my scripts and putting subroutines into modules, just wondering how I reference a subroutine located in a module?
sub creationDateTime {
my $creationDate = $yn . $mn . $dn . $hn . $minn . $sn;
return $creationDateTime;
}
1;
#!/usr/bin/perl
#createUser cgi
use strict;
use warnings;
use dtm qw(creationDateTime);
creationDateTime();
#OR
use dtm qw(creationDateTime);
$creationDateTime = creationDateTime();
Doesn't seem to return a value to the createUser.cgi using either method, as I get uninitialised variable warnings. Basically I am trying to assign the return value of the subroutine creationDateTime() in the module to the scalar variable $creationDateTime in createUser.cgi.
A_Tame_Lion
04-17-2011, 11:46 PM
Actually I just got this to work! Had a typo in my script!
Thanks guys!
A_Tame_Lion
04-20-2011, 07:05 AM
Actually I think I spoke to soon! Although I can pass arrays into a subroutine, I am having difficulty passing a single scalar variable into a subroutine, say for instance a scalar variable date formatted yyyy/mm/dd to be passed from a cgi script to a subroutine held in a separate module, and then for the subroutine to manupilate the date and return it to the main cgi script.
In the main script I have:
$age_ref should containt something like 19720512 or 1972/05/12 (date format)
$ucAge = dtm::age(\$age_ref);
In the dtm module I have:
sub age {
my $yc = "";
my $adjm = "";
foreach ($_) {
my $num = $_;
$num =~ s/\D//g;
my $cy = substr $num, 0, 4;
my $cm = substr $num, 4, 2;
my $cd = substr $num, 6, 2;
I have tried using $_ to signify I am only evaluating one scalar variable, can't get it to work?? Any ideas?
Sixtease
04-20-2011, 07:15 AM
foreach ($_) { ... } means: Take whatever is in the $_ variable and assign it to the $_ variable for the duration of the loop. That's almost never what you want.
Apart from that, you make two mistakes if I see correctly: 1) you never use the parameter passed to the subroutine (@_) and 2) you pass a reference to the scalar, which is needless: just pass the variable.
$age = '1972/05/12';
$ucAge = dtm::age($age);
sub age {
my ($num) = @_;
# do your thing
}
Btw. you use the $age variable in the subroutine without declaration (my $age), so you're probably clobbering your $age variable in the global namespace, which you also likely don't want.
A_Tame_Lion
04-20-2011, 07:42 AM
Thanks Sixtease. I had the subroutine working correctly when it was in the main script but thought I had to pass a reference to the subroutine when it was moved to a package, think I got confused in something I read online. So it seems whether you are evaluating a scalar or an array (as input to a subroutine), or expecting a scalar or array as output from a subroutine the @_ method is the way to go.
I'll take your advice and scope the other variable.
A_Tame_Lion
05-03-2011, 08:45 AM
Actually, I just found out my installation of Catalyst is incomplete despite hours of CPAN installation, so because of time constraints I am reverting - for now to my first approach.
sub imageHandlerUC {
my ($image_ref) = @_;
my $safe_filename_characters = "a-zA-Z0-9_.-";
my $imageFolder = ($image_ref->[0]);
my $upload_dir = "images/" . $imageFolder . "/";
my $filename = ($image_ref->[1]);
if ( !$filename ) {
print "There was a problem uploading your photo (try a smaller file).";
exit;
}
if ( $filename =~ /^([$safe_filename_characters]+)$/ ) {
$filename = $1;
}
else {
die "Filename contains invalid characters";
}
my $upload_filehandle = $image;
open ( UPLOADFILE, ">$upload_dir/$filename" ) or die "$!";
binmode UPLOADFILE;
while ( <$upload_filehandle> ) { print UPLOADFILE; } close UPLOADFILE;
Keep getting the error "Can't use string ("900") as an ARRAY ref while "strict refs" in use", referring to the
my $imageFolder = ($image_ref->[0]);
line of code. What I have done is put three scalar variables into an array in the main script, then I want to unpack those variables from the array in this subroutine located in a module and assign each one of those variables to a scalar. The code looks exactly the same as I have in some other subroutines but I can't get past this error???
$image_ref->[0] should hold the value of 900, and it is due to get concatenated into the path of a file upload (so the image is saved in the right folder) and be written to a MySQL database.
$image_ref->[1] is the picture file to be uploaded
$image_ref->[2] is a username, which the image file is due to be renamed to (not in the script yet!).
What am I doing wrong here?
A_Tame_Lion
05-03-2011, 11:16 AM
Just got this to work, the problem was the subroutine was being called 3 times in the main script, as soon as I fixed that it works as expected. Just trying to figure out now how to create new directories from within the script
Sixtease
05-04-2011, 02:52 AM
Perl has a mkdir (http://perldoc.perl.org/functions/mkdir.html) function.
A_Tame_Lion
05-04-2011, 04:51 AM
Yes, saw that but chose the File::Path module.
webdeveloper.com
Copyright Internet.com Inc., All Rights Reserved.