Is there an elegant way to create dynamic array in MATLAB?

Is there an elegant way to create dynamic array in MATLAB?
For instance, my program has a loop, as program iterates over the loop, some numeric values will be generated and should be stored in an array. However, I cannot know the exact count of these generated values because their generation depends on an if-else logic. How to pre-allocate the size of this array used for storing these values.

 Accepted Answer

It is much more efficient to allocate too much memory (as long as it fits into the available RAM) than letting an array grow. Usually you can determin a maximum size and crop the array afterwards:
n = 1000;
A = zeros(n, 6);
i = 0;
for i = 1:n
if rand < 0.5
i = i + 1;
A(i, :) = rand(1, 6);
end
end
A = A(1:i, :);
But sometimes estimating an upper limit for the size is impossible. Then you can pre-allocate in chunks. This has actually the same problem as an omitted pre-allocation, but the with a very much smaller effect:
n = 1000;
A = zeros(0, 6);
i = 0;
imax = 1000;
for i = 1:n
if rand < 0.5
i = i + 1;
if i > imax % Allocate in chunks of 1000 rows
imax = imax + 1000; % EDITED
A(imax, :) = 0;
end
A(i, :) = rand(1, 6);
end
end
A = A(1:i, :);

6 Comments

@Jan, allocating in chucks is good. Perhaps, you meant to update imax before allocating. As it is, you overwrite the previous value in the inner most conditional.
@Jonathan: Yes, imax must be updated before the re-allocation. Thanks for the careful reading.
@Jan, I should have been more careful. Your for loop variable should be difference than i!
@Jonathan: I know, that avoiding i and j is recommended in the Matlab documentation. And in the same documentation I find a lot of examples, which do use i as a counter in a FOR loop. I personally never hat a problem with using i in simple loops, because I avoid terms like 2*i and use 2i instead.
As others correctly noted, it is not a good practice to use a not pre-allocated array as it highly reduces your running speed. There are two ways to do it;
Solution 1: In fact it is possible to have dynamic structures in Matlab environment too. However, it is not a native Matlab structure. Recently, I had to write a graph traversal script in Matlab that required a dynamic stack. To do so, you can simply use a Stack from java libraries for example. It is quite powerful and you can handle almost all different types of data! You can simply borrow this from java within matlab by;
% imports stack utility from java in matlab
import java.util.*;
% then use following commands to deal with stack
A = Stack();
A.push(i); % inserts i on top of stack A
A.pop(); %pops out an element
Solution 2: As Jan's said , preallocate an overestimated large array and then trim it after your operations.
There is one additional problem with the above code, and maybe this is new since I am 10 years late. When The original code runs
n = 10;
A = zeros(n, 6);
i = 0;
for i = 1:n
if rand < 0.5
i = i + 1;
A(i, :) = rand(1, 6);
end
end
A = A(1:i, :);
the answer is
A
A = 10×6
0 0 0 0 0 0 0.6024 0.4031 0.9445 0.3273 0.6586 0.4921 0.1816 0.4943 0.9874 0.1688 0.5664 0.6148 0.2693 0.4955 0.3752 0.8397 0.3598 0.6651 0.1448 0.4836 0.2823 0.2843 0.2805 0.2648 0 0 0 0 0 0 0.3728 0.0136 0.2125 0.1451 0.0941 0.3619 0.1938 0.3420 0.8465 0.5127 0.5931 0.6998 0.9429 0.0022 0.6681 0.0910 0.1146 0.0129 0.5347 0.1333 0.9755 0.0400 0.1895 0.7716
Which is not cropped to remove the zeros. I think the problem is that while i is set to 0 first, the for loop resets the value of i, negatting the counter. If the indexing variable for the loop is changed to j
n = 10;
A = zeros(n, 6);
i = 0;
for j = 1:n
if rand < 0.5
i = i + 1;
A(i, :) = rand(1, 6);
end
end
B = A(1:i, :);
we get
B
B = 6×6
0.8849 0.0960 0.3774 0.6824 0.7197 0.0934 0.9566 0.9143 0.0197 0.0182 0.4071 0.0905 0.2312 0.5482 0.0047 0.4678 0.7558 0.6598 0.9475 0.7795 0.7933 0.7032 0.8785 0.4811 0.4386 0.0435 0.0677 0.3756 0.7877 0.0213 0.8197 0.9326 0.0958 0.6741 0.8373 0.2618
the actual cropped data.
Let me know if I am missing something :)

Sign in to comment.

More Answers (3)

liangjian,
You can preallocate based on the number of iterations. Try something like this.
numIter = 100;
array = nan(numIter, 3);
for i = 1:numIter
if randi(2) == 1
newValues = [i 10*i 100*i];
array(i,:) = newValues;
end
end
array = array(~isnan(array(:,1)),:);
Sure, just don't do anything and that's the way MATLAB works. Just start using the variable. However it's better to preallocate, like Jan and Jonathan told you, even if it's only an estimate. If you preallocate with zeros() or something, and then you can adjust the size automatically later just by assigning to it. For example:
a = zeros(100,100); % Preallocate a guess
a(200, 300) = 4; % Automatically adjusts size.
A clever trick by Loren Shore to preallocate is to just assign the lower right element of the array, for example:
b(480,640) = 0;
Note though that only the lower right element takes on the value you set, not the whole array. The rest of the array will be zero. For example:
b(4, 2) = 40
b =
0 0
0 0
0 0
0 40
As others correctly noted, it is not a good practice to use a not pre-allocated array as it highly reduces your running speed. There are two ways to do it;
Solution 1: In fact it is possible to have dynamic structures in Matlab environment too. However, it is not a native Matlab structure. Recently, I had to write a graph traversal script in Matlab that required a dynamic stack. To do so, you can simply use a Stack from java libraries for example. It is quite powerful and you can handle almost all different types of data! You can simply borrow this from java within matlab by;
% imports stack utility from java in matlab
import java.util.*;
% then use following commands to deal with stack
A = Stack();
A.push(i); % inserts i on top of stack A
A.pop(); %pops out an element
Solution 2: As Jan's said , preallocate an overestimated large array and then trim it after your operations.

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Asked:

on 11 Nov 2011

Commented:

on 23 Feb 2023

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!