Reputation: 4686
How can I preallocate an array of structs in MATLAB? I want to preallocate "a" in this example so that it does not resize several times.
a = []
for i = 1:100
a(i).x = i;
end
Upvotes: 52
Views: 60862
Reputation: 1
using cell2struct is by far the fastest method I could figure out. Just check the following code to make a comparison:
clear;
N = 10000;
cel2s=0;
repm=0;
for i=1:100
a=0.0; b=0.0;
tic;
a = cell2struct(cell(1,N), {'x'}, 1 );
cel2s = cel2s + toc;
tic;
b = repmat(struct('x',1), N, 1 );
repm = repm + toc;
end
disp(['cell2struct preallocation: ', num2str(cel2s/100)]);
disp(['repmat preallocation : ', num2str(repm/100)]);
disp(['speedup : ', num2str(fix( repm/cel2s ) ) , ' X']);
Typical results show a mean speedup around 19 times! wrt repmat method:
cell2struct preallocation: 1.4636e-05
repmat preallocation : 0.00028794
speedup : 19 X
Upvotes: 0
Reputation: 2028
Using repmat
is by far the most efficient way to preallocate structs :
N = 10000;
b = repmat(struct('x',1), N, 1 );
This is ~10x faster using Matlab 2011a than preallocating via indexing, as in
N = 10000;
b(N).x = 1
The indexing method is only marginally faster than not preallocating.
No preallocation: 0.075524
Preallocate Using indexing: 0.063774
Preallocate with repmat: 0.005234
Code below in case you want to verify.
clear;
N = 10000;
%1) GROWING A STRUCT
tic;
for ii=1:N
a(ii).x(1)=1;
end
noPreAll = toc;
%2)PREALLOCATING A STRUCT
tic;
b = repmat( struct( 'x', 1 ), N, 1 );
for ii=1:N
b(ii).x(1)=1;
end;
repmatBased=toc;
%3)Index to preallocate
tic;
c(N).x = 1;
for ii=1:N
c(ii).x(1)=1;
end;
preIndex=toc;
disp(['No preallocation: ' num2str(noPreAll)])
disp(['Preallocate Indexing: ' num2str(preIndex)])
disp(['Preallocate with repmat: ' num2str(repmatBased)])
Results in command window:
No preallocation: 0.075524
Preallocate Indexing: 0.063774
Preallocate with repmat: 0.0052338
>>
P.S. I'd be interested to know why this is true, if anyone can explain it.
Upvotes: 80
Reputation: 456
The way this is supposed to be done, and the simplest is
a=struct('x',cell(1,N));
If you fix the missing "tic" and add this method to the benchmarking code presented by jerad, the method I propose above is a bit slower than repmat but much simpler to implement, here is the output:
No preallocation: 0.10137
Preallocate Indexing: 0.07615
Preallocate with repmat: 0.01458
Preallocate with struct: 0.07588
The reason that repmat is faster is because a value to each 'x' field is assigned during the pre-allocation, instead of leaving it empty. If the above pre-allocation technique is changed so we start with all the x fields with a value (one) assigned, like this:
a=cell(1,N);
a(:)={1};
d=struct('x',a);
Then, the benchmarking improves a lot, been very close or some time faster than repmat. The difference is so small that every time I run it it changes which one is faster. Here an output example:
No preallocation: 0.0962
Preallocate Indexing: 0.0745
Preallocate with repmat: 0.0259
Preallocate with struct: 0.0184
Conversely, if the repmat pre-allocation is changed to set the field empty, like this
b = repmat( struct( 'x', {} ), N, 1 );
All the speed advantage is lost
Upvotes: 3
Reputation: 314
Instead of pre-allocating the array of structs it may be easier to reverse the loop. In this way the array is allocated in the first iteration and the rest of the iterations are used to fill the structs.
a = []
for i = 100:-1:1
a(i).x = i;
end
Upvotes: -1
Reputation: 4121
According to this answer, there's also another way to do it:
[a.x] = deal(val);
where val
is the value you want to assign to every element of the struct.
The effect of this command is different from those of the others, as every x
field of every structure a
will be assigned the val
value.
Upvotes: -1
Reputation: 74930
There's a bunch of ways you can initialize a structure. For example, you can use the struct
command:
a(1:100) = struct('x',[]);
which sets all fields x
to empty.
You can also use deal
to create and fill the structure if you know what data should go in there
xx = num2cell(1:100);
[a(1:100).x]=deal(xx{:});
a(99).x
ans =
99
Or you can use struct
again (note that if a field of the structure should be a cell array, the cell needs to be enclosed in curly brackets!)
a = struct('x',xx)
Upvotes: 11
Reputation: 26069
There's a nice discussion about this in Loren on the Art of MATLAB blog.
If I understand you correctly, here's a ways to initialize the struct you want:
a(100).x = 100;
With this method, we can see that elements are filled in with empty arrays.
Upvotes: 12