How to pre-allocate for unknown size vector?

조회 수: 147 (최근 30일)
JAI PRAKASH
JAI PRAKASH 2018년 11월 24일
답변: Walter Roberson 2020년 1월 1일
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' ?

채택된 답변

Image Analyst
Image Analyst 2018년 11월 24일
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)

추가 답변 (2개)

John D'Errico
John D'Errico 2018년 11월 24일
편집: John D'Errico 2018년 11월 24일
There are several simple ways to do this.
  1. 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.
  2. 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
John D'Errico
John D'Errico 2018년 11월 25일
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.
JAI PRAKASH
JAI PRAKASH 2018년 11월 25일
OK thank you very much

댓글을 달려면 로그인하십시오.


Walter Roberson
Walter Roberson 2020년 1월 1일
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.

카테고리

Help CenterFile Exchange에서 Logical에 대해 자세히 알아보기

태그

제품


릴리스

R2018b

Community Treasure Hunt

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

Start Hunting!

Translated by