How to pre-allocate for unknown size vector?
    20 views (last 30 days)
  
       Show older comments
    
    JAI PRAKASH
      
 on 24 Nov 2018
  
    
    
    
    
    Answered: Walter Roberson
      
      
 on 1 Jan 2020
            vector = [];
for i = 1:1000000
    r = randi([1 4],1,1); % a random integer generator between 1 and 4
    vector = [vector 1:r];
end
% 1. How to preallocate 'vector' ?
% 2. And get rid of unassigned variables ?
% 3. Preallocation considering Matlab coder compatability perspective !!
% 4. Can i use 'coder.nullcopy' ?
Accepted Answer
  Image Analyst
      
      
 on 24 Nov 2018
        Here is one way:
numIterations = 4;
maxLength = 4;
vector = zeros(1, numIterations * maxLength);
lastIndex = 0;
for k = 1: numIterations
	r = randi([1 maxLength],1,1); % a random integer generator between 1 and 4
	vector(lastIndex+1 : lastIndex + r) = 1 : r;
	lastIndex = lastIndex + r;
end
% Crop off unused elements
vector = vector(1:lastIndex)
0 Comments
More Answers (2)
  John D'Errico
      
      
 on 24 Nov 2018
        
      Edited: John D'Errico
      
      
 on 24 Nov 2018
  
      There are several simple ways to do this.
- Over-allocate the array. r will never be larger than 4. Therefore, the array will never be larger than 4e6 in length. So preallocate r to be of size 1x4e6. Now just index into the array, keeping a running count of where you stuffed the last elements into the array. At the end, just delete the unused elements. I would pre-allocate with NaNs, so you know what was unused.
- Preallocate a cell array instead. You know how many passes through the loop. So create a cell array of size 1x1e6. Then stuff one cell at each iteration of the loop. At the end, just collapse the cell array into a flat array using cell2mat.
There are other ways to do this, but those are the easy ways. #2 is by far the better, and simpler, so use it. It will be fairly efficient, and very easy to read and debug. For example...
C = cell(1,1e6);
for i = 1:1000000
    r = randi([1 4],1,1); % a random integer generator between 1 and 4
    C{i} = 1:r;
end
vector = cell2mat(C);
whos vector
  Name        Size                    Bytes  Class     Attributes
  vector      1x2501228            20009824  double              
3 Comments
  John D'Errico
      
      
 on 25 Nov 2018
				Then better will be #1 I guess. It requires only that you keep acounter of where you are stuffing new elements into your array, then delete the unused portion of the array at the end. Extra bookkeeping that the cell array solution allows you to avoid.
I would point out that #1 is the solution that Image Analyst posed.
  Walter Roberson
      
      
 on 1 Jan 2020
        Start with an empty vector. Keep track of the number of positions used so far (which will start at 0)
At any point when you need to insert a 1:r, check to see if there are at least r positions remaining in the vector.  If there are not at least r positions remaining in the vector, extend the vector by max() of r and (number of iterations remaining times average length of extension (that is, (4+1)/2)) . End if. Now insert the 1:r and increment the count of used values.
At end, trim out any unused locations.
vector = [];
vused = 0;
mrand = 4;
avgrand = (mrand+1)/2;
numIterations = 100000;
for i = 1 : numIterations
    Lvec = length(vector);
    r = randi(4);
    if Lvec-vused < r
        extend_to = Lvec + max(r, ceil((numIterations - i)*avgrand));
        fprintf('extending to length %d on iteration %d\n', extend_to, i);
        vector(extend_to) = 0;   %zero fills between current end and here
    end
    vector(vused+1:vused+r) = 1:r;
    vused = vused + r;
end
fprintf('trimming %d entries\n', length(vector)-vused);
vector(vused+1:end) = [];
If you test this, you will see that the number of extensions is quite low, often being only 2 or 3 times. 
0 Comments
See Also
Categories
				Find more on Downloads in Help Center and File Exchange
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!



