How to pre-allocate for unknown size vector?
114 次查看(过去 30 天)
显示 更早的评论
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
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)
0 个评论
更多回答(2 个)
John D'Errico
2018-11-24
编辑:John D'Errico
2018-11-24
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 个评论
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.
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.
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Logical 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!