Perl: equivalent of "ubound" in VBA - arrays

Now that on day 2 of Perl I see that arrays start with element(0) too, how do I get the last index of an array like ubound in VBA rather than the size of it using scalar(#array)?
Is the use of $size = $#array a good way or is there something similar to scalar(#array)?

Perl's arrays always start empty.
my #array; # equivalent
my #array = (); #
To get the highest index, use $#array.
my #array = qw(a b c);
print $#array; # 2
If the array is empty, $#array will be -1.

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

Perl array element comparing

I am new in Perl programming. I am trying to compare the two arrays each element. So here is my code:
#!/usr/bin/perl
use strict;
use warnings;
use v5.10.1;
my #x = ("tom","john","michell");
my #y = ("tom","john","michell","robert","ricky");
if (#x ~~ #y)
{
say "elements matched";
}
else
{
say "no elements matched";
}
When I run this I get the output
no elements matched
So I want to compare both array elements in deep and the element do not matches, those elements I want to store it in a new array. As I can now compare the only matched elements but I can't store it in a new array.
How can I store those unmatched elements in a new array?
Please someone can help me and advice.
I'd avoid smart matching in Perl - e.g. see here
If you're trying to compare the contents of $y[0] with $x[0] then this is one way to go, which puts all non-matches in an new array #keep:
use strict;
use warnings;
use feature qw/say/;
my #x = qw(tom john michell);
my #y = qw(tom john michell robert ricky);
my #keep;
for (my $i = 0; $i <$#y; $i++) {
unless ($y[$i] eq $x[$i]){
push #keep, $y[$i];
}
}
say for #keep;
Or, if you simply want to see if one name exists in the other array (and aren't interested in directly comparing elements), use two hashes:
my (%x, %y);
$x{$_}++ for #x;
$y{$_}++ for #y;
foreach (keys %y){
say if not exists $x{$_};
}
It would be well worth your while spending some time reading the Perl FAQ.
Perl FAQ 4 concerns Data Manipulation and includes the following question and answer:
How do I compute the difference of two arrays? How do I compute
the intersection of two arrays?
Use a hash. Here's code to do both and more. It assumes that each
element is unique in a given array:
my (#union, #intersection, #difference);
my %count = ();
foreach my $element (#array1, #array2) { $count{$element}++ }
foreach my $element (keys %count) {
push #union, $element;
push #{ $count{$element} > 1 ? \#intersection : \#difference }, $element;
}
Note that this is the symmetric difference, that is, all elements
in either A or in B but not in both. Think of it as an xor
operation.

Remove elements of a Perl array

Is there an easy way to remove n consecutive elements of a Perl array (thus making it shorter in length)?
You are looking for the Perl builtin function splice, which lets you pick a starting point, number of elements to remove, and an optional replacement list.
my #array = 0 .. 9;
my #slice = splice #array, 3, 3;
say "#slice"; # prints "3 4 5"
say "#array"; # prints "0 1 2 6 7 8 9"
say 0 + #array; # prints 7
You can use splice to remove array elements.
As the other answers indicated, splice works. As an alternative approach (TIMTOWTDI, after all), if you have the upper and lower indices for the n consecutive elements that you want removed, then you can do it via grep and an array slice. For example:
use strict;
use warnings;
my #a=("a".."z");
#We will remove the letters "e" through "u"
my $lower=4;
my $upper=20;
print "$_\n" foreach(#a[grep{$_<$lower or $_>$upper}0..$#a]);
The output is:
a
b
c
d
v
w
x
y
z

In Perl, what is the difference between #array[1] and $array[1]?

I have been studying array slices and frankly do not see the difference between choosing #array[1] and $array[1]. Is there a difference?
#!/usr/bin/perl
#array = (1,3);
print "\nPrinting out full array..\#array\n";
print "#array\n";
print "\n";
print "Printing out \#array[1]\n";
print "#array[1]\n";
print "Printing out \$array[1]\n";
print "$array[1]\n";
print "\n\n";
This is a FAQ.
The two forms are likely to work the same way in many contexts (but not all, as you can see from the example in the FAQ), but $array[1] expresses the intent more clearly.
$ and # are called sigils: hear what the sigils tell you
When you see $ you are dealing with a single thing.
When you see # you have a list of things.
#array[ 1 ] is a slice, a list with selected elements from the #array list. You have put only an element in this slice, the second element of #array, but it's a list anyway.
$array[ 1 ] is the second element of the list, a single value, a scalar.
#hash{ 'one', 'two' } is another kind of slice: this time we sliced an hash ( %hash ), obtaining a list with values corresponding to keys one and two.
Where's the difference? Although the difference is thin, you should avoid single element slices when you want a single value. Remember that on the right hand side of an expression, single element slices behave like scalars, but when they are on the left hand side of an expression they become a list assignment: they give list context to the expression.
If still you aren't feeling comfortable with the difference between scalar and list context, please don't use single element slices in order to avoid unexpected results in certain situations ( for instance when using the line input operator < > ).
Check the docs and happy Perl.
You already have your answer from Keith and Marco: # means list, $ means scalar (single value). I have more to add that does not fit in a comment.
You do not notice the difference because you are using a slice of one element. However, try this:
use warnings;
use strict;
use v5.10; # to enable say
my #array = (1 .. 10);
say "#array[2 .. 4]"; # [2,3,4] == "3 4 5"
say "#array[1,4,7]"; # == "2 5 8"
Here's some pointers to your code.
use strict;
use warnings;
There really is no excuse for not using these two. There is hardly any circumstance where it is better -- or easier -- to not use them. This holds especially true when you are experimenting and trying to learn perl.
If you had been using warnings, you would have gotten this additional information:
Scalar value #array[1] better written as $array[1]
Which basically is exactly the answer you have been given here, albeit said in the perl compiler's terse language.
Also, using print the way you do it is hard on the eyes. Make use of perl's flexibility:
#!/usr/bin/perl
use strict;
use warnings;
my #array = (1 .. 10);
print "
Printing out full array..\#array
#array
Printing out \#array[1]
#array[1]
Printing out \$array[1]
$array[1]
";
As you can see, this will print out newlines in a WYSIWYG fashion.
There are two differences:
The «1» is evaluated in list context in the case of the array slice (#foo[1]), but in scalar context in the case of the array indexing ($foo[1]). This has no functional effect.
#foo[1] gives a warning.
Good question - here's some differences:
$a[0] = localtime; print #a; # this prints: Tue Nov 1 18:51:13 2011
#a[0] = localtime; print #a; # this prints the amount of seconds, e.g. 13
$a[0] = grep{}, qw(6 2 8); print #a; # this prints: 3
#a[0] = grep{}, qw(6 2 8); print #a; # this prints: 6
$a[0] = reverse ("a", "b"); print #a; # this prints: ba
#a[0] = reverse ("a", "b"); print #a; # this prints: b
$a[0] = ("a", "b"); print #a; # this prints: b
#a[0] = ("a", "b"); print #a; # this prints: a
It doesn't matter if the slice is [1]. You can create more examples by finding functions that give different results when evaluated in different contexts.
Explanation of the latter (4th) example:
The $ in $a[0] creates a scalar context. The context affects the way the comma operator works, creating different results:
"Binary "," is the comma operator. In scalar context it evaluates its left argument, throws that value away, then evaluates its right argument and returns that value."
http://perldoc.perl.org/perlop.html#Comma-Operator
Hence: b
To understand the line beginning with: #a[0] consider:
($a, $b, $c) = ("a", "b", "c", "d"); # here the "d" is discarded
print $a, $b, $c; # this prints: abc
($a, $b) = ("a", "b", "c"); # here the "c" is discarded
($a) = ("a", "b"); # here the "b" is discarded
($a[0]) = ("a", "b"); # here the "b" is discarded
It would appear that parentheses at the beginning of the line create a list context. This is pretty much what it says at: http://docstore.mik.ua/orelly/perl4/prog/ch02_07.htm
"Assignment to a list of scalars also provides a list context to the righthand side, even if there's only one element in the list"
# at the beginnning of a line also creates a list context:
#a[0] = ("a", "b") means evaluate the RHS in the same way as above i.e. discard the "b"

Sorting Arrays in Perl?

I am getting an error while trying to sort a simple array...
The ERROR reads: "use of uninitialized value in numeric comparison (<=>) at file.pl line #"
#!/usr/bin/perl
use strict
use wardings
use Data::Dumper
my #array
my $array
$array[1]= 5
$array[2]= 2
$array[3]= 3
$array[4]= 4
$array[5]= 1
sub numerically {$a <=> $b}
my #sortedarray = sort numerically #array;
print "#sortedarray\n";
I am just trying to sort the array to get:
1 2 3 4 5
I am new at perl so this might just be something stupid, but please help me... Thanks
Arrays are indexed starting at 0. The error comes from trying to sort the array when $array[0] is undefined.
Update: Also, in perl, one would write:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my #array = qw(1 2 3 4 5);
sub numerically {$a <=> $b}
my #sortedarray = sort numerically #array;
print "#sortedarray\n";
There is no point in declaring $array -- that would be a scalar. You are only working with the array #array, even though it is called with a $. Please read the perl documentation.
first of all, you need a semi-colon at the end of every statement. second, you're not using Data::Dumper, so why do you include it? You also don't need to declare the sub:
#!/usr/bin/env perl
use strict;
use warnings;
my #sorted = sort {$a <=> $b} qw (4 2 3 1 5);
print "#sorted\n";
And there we have it.
You're missing a shedload of semicolons.
It's warnings, not wardings.
Element 0 in your array is undefined.

Resources