Reputation: 1896
I'm trying to print out the size of my array. I've followed a few other questions like this one on Stack Overflow. However, I never get the result I want.
All I wish for in this example is for the value of 3 to be printed as I have three indexes. All I get, from both print methods is 0.
my @arr;
$arr{1} = 1;
$arr{2} = 2;
$arr{3} = 3;
my $size = @arr;
print $size; # Prints 0
print scalar @arr; # Prints 0
What am I doing wrong, and how do I get the total size of an array when declared and populated this way?
Upvotes: 1
Views: 4408
Reputation: 1124
You may be thinking that you are instantiating an element of @arr when you are typing in the following code:
$arr{1} = 1;
However, you are instantiating a hash doing that. This tells me that you are not using strict or you would have an error. Instead, change to brackets, like this:
$arr[1] = 1;
Upvotes: 0
Reputation: 53478
First off:
my @arr;
$arr{1} = 1;
$arr{2} = 2;
$arr{3} = 3;
is nonsense. {}
is for hash keys, so you are referring to %arr
not @arr
. use strict;
and use warnings;
would have told you this, and is just one tiny fragment of why they're considered mandatory.
To count the elements in an array, merely access it in a scalar context.
print scalar @arr;
if ( $num_elements < @arr ) { do_something(); }
But you would need to change your thing to
my @arr;
$arr[1] = 1;
$arr[2] = 2;
$arr[3] = 3;
And note - the first element of your array $arr[0]
would be undefined.
$VAR1 = [
undef,
1,
2,
3
];
As a result, you would get a result of 4. To get the desired 'count of elements' you would need to filter the undefined items, with something like grep
:
print scalar grep {defined} @arr;
This will take @arr
filter it with grep
(returning 3 elements) and then take the scalar value - count of elements, in this case 3.
But normally - you wouldn't do this. It's only necessary because you're trying to insert values into specific 'slots' in your array.
What you would do more commonly, is use either a direct assignment:
my @arr = ( 1, 2, 3 );
Or:
push ( @arr, 1 );
push ( @arr, 2 );
push ( @arr, 3 );
Which inserts the values at the end of the array. You would - if explicitly iterating - go from 0..$#arr
but you rarely need to do this when you can do:
foreach my $element ( @arr ) {
print $element,"\n";
}
Or you can do it with a hash:
my %arr;
$arr{1} = 1;
$arr{2} = 2;
$arr{3} = 3;
This turns your array into a set of (unordered) key-value pairs, which you can access with keys %arr
and do exactly the same:
print scalar keys %arr;
if ( $elements < keys %arr ) { do_something(); }
In this latter case, your hash will be:
$VAR1 = {
'1' => 1,
'3' => 3,
'2' => 2
};
I would suggest this is bad practice - if you have ordered values, the tool for the job is the array. If you have 'key' values, a hash is probably the tool for the job still - such as a 'request ID' or similar. You can typically tell the difference by looking at how you access the data, and whether there are any gaps (including from zero).
So to answer your question as asked:
my $size = @arr;
print $size; # prints 0
print scalar @arr; # prints 0
These don't work, because you never insert any values into @arr
. But you do have a hash called %arr
which you created implicitly. (And again - use strict;
and use warnings;
would have told you this).
Upvotes: 18
Reputation: 29844
I just thought there should be an illustration of your code run with USUW (use strict/use warnings) and what it adds to the troubleshooting process:
use strict;
use warnings;
my @arr;
...
And when you run it:
Global symbol "%arr" requires explicit package name (did you forget to declare "my %arr"?) at - line 9.
Global symbol "%arr" requires explicit package name (did you forget to declare "my %arr"?) at - line 10.
Global symbol "%arr" requires explicit package name (did you forget to declare "my %arr"?) at - line 11.
Execution of - aborted due to compilation errors.
So USUW.
Upvotes: 0
Reputation: 2331
You are initializing a hash, not an array.
To get the "size" of your hash you can write.
my $size = keys %arr;
Upvotes: 2