Eli
Eli

Reputation: 38949

Can I Initialize an Array to a Given Size in Perl?

I have a section in my code where I know I will need an array, and I know exactly how many elements that array will need to have. This section of code will be repeated a lot, so I'd could get some very big time savings by first initializing that array to the size I know it will need and then filling it up vs just pushing items on (pushing would be O(n) as opposed to filling up already created spaces, which would be O(1)).

That said, I can't seem to find any elegant way of initializing an array to a given size, and I have no idea why. I know I can do:

my @array; $array[49] =0;

to get a 50 item array, but that looks really ugly to me and I feel as though there must be a better way. Ideas?

Upvotes: 22

Views: 26669

Answers (7)

user1067305
user1067305

Reputation: 3481

An advantage of predefining the array length is that items can then be filled in any convenient order, rather than in strict order, as required by push. That is much less error prone.

Upvotes: 0

cbrandolino
cbrandolino

Reputation: 5883

Your way is great, and so is DVK's. A way to do it in a single command might be:

@array = (0 .. 49);

But I'm not sure if it's more elegant, since it assigns a value between 1 and 49 to each element, but it's probably more intuitive to understand for a programmer not much into Perl's syntax.

Upvotes: 1

Andy Lester
Andy Lester

Reputation: 93676

  1. The first rule of Optimization Club is, you do not Optimize.
  2. The second rule of Optimization Club is, you do not Optimize without measuring.

Measure, measure, measure before you go and assume that you can do it faster by faking out Perl. Perl's been doing the optimization of common usage a lot longer than you have. Trust it.

Upvotes: 12

Emil Perhinschi
Emil Perhinschi

Reputation: 1283

Preallocating might not help much with the speed, but it might help with returning the memory to the system if the chunks allocated are big enough

Upvotes: 1

metdos
metdos

Reputation: 13929

Instead of a specific value use undef

my @array;
$array[49] = undef;

Upvotes: 2

Brian
Brian

Reputation: 15706

Whenever you're thinking about doing this type of optimization, do some profiling! The result may not be what you expect. For instance, I used the following quick script to test your theory that pre-allocating the array is faster:

for ( my $loops = 0; $loops < 100000; $loops++ )
{
    my @arr;

    for ( my $foo = 0; $foo < 50; $foo++ ) {
        push @arr, 'bar';
    }
}

That took 2.13 seconds.

for ( my $loops = 0; $loops < 100000; $loops++ )
{
    my @arr;
    $arr[49] = 0;

    for ( my $foo = 0; $foo < 50; $foo++ ) {
        $arr[$foo] = 'bar';
    }
}

That took 2.16 seconds (I ran both tests several times). So it actually ends up being faster to just let perl handle allocating the array as necessary.

Update

After making changes suggested by ysth, the numbers make a bit more sense: 2.27 seconds for the "push" method, and 2.21 for pre-allocation. Even so, I would question whether such an optimization would really save any time (the difference was only 0.06 seconds after 100,000 iterations).

Upvotes: 6

DVK
DVK

Reputation: 129403

To be honest your way is perfectly fine, as is explicitly changing the size of the array: $#array = 49;;

Upvotes: 17

Related Questions