Reputation: 38949
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
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
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
Reputation: 93676
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
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
Reputation: 13929
Instead of a specific value use undef
my @array;
$array[49] = undef;
Upvotes: 2
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
Reputation: 129403
To be honest your way is perfectly fine, as is explicitly changing the size of the array: $#array = 49;
;
Upvotes: 17