1

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?

4
  • 5
    And if you use $arr[1] = 1;. etc? Always use strict; use warnings;! Commented Jan 12, 2016 at 14:33
  • good point about the strict & warnings. I'd still like to stick to the question, how can i get a count result when declared using { } instead of [ ]? Commented Jan 12, 2016 at 14:36
  • 11
    What did enabling strict and warnings show you? Something about a missing %arr, perhaps? $arr{1} modifies %arr, not @arr. You're going to have to stick to Perl's syntax. Commented Jan 12, 2016 at 14:38
  • 10
    Failing to use strict; is your biggest mistake. Commented Jan 12, 2016 at 14:41

4 Answers 4

18

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).

Sign up to request clarification or add additional context in comments.

1 Comment

Instead of showing them how to grep out the undefined elements, I think it makes more sense to just show them how to populate an array starting with index zero. I can just picture them using that grep every time they create a new array because Perl has this "weird bug" that always puts an undefined element at the beginning of arrays.
2

You are initializing a hash, not an array.

To get the "size" of your hash you can write.

my $size = keys %arr;

Comments

0

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.

Comments

0

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;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.