Fill in array with different lengths of variables at different locations

2 views (last 30 days)
What is the most efficient way to fill in an array with a problem as below:
A = [4 6 7 8 9 13 15 20];
I want to fill the array so that a condition is satisfied, in this example that the difference between each array entry is not more than 1.
In a way that the result is:
result = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20];
Of course, my condition is different but this is the same flow of question. My issue with for loops is that the predefined length of the array is changing.

Accepted Answer

dpb
dpb on 29 Mar 2021
The trick for stuff like this is to "grow" from the back to the front -- so the indices you haven't gotten to yet don't change by the changes you have made:
A=[4 6 7 8 9 13 15 20]; % sample data vector
% the engine
ix=flip(find(diff([A(1) A])>1)); % find locations with diff>1; reverse order
for i=1:numel(ix) % for each "hole" location found
vfill=[A(ix(i)-1)+1:A(ix(i))-1]; % compute the missing values between existing elements
A=[A(1:ix(i)-1) vfill A(ix(i):end)]; % insert in place
end
For your sample case and fill-in rule, the above results in:
>> A
A =
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
>>
NB: The other "trick" not outlined is in the calculation of the ix vector, I augmented A with A(i) so the short-by-one indices returned by find on the diff() result would be in terms of the original length of A, not the shorter length.
Using A(1) ensures there isn't a true value in the first location as a result of diff(); one could just as well augment the resultant output of the logical test or add one to the result and not augment.
Or, of course, use "+1" for all the addressing or treat the location as the end of the complete sequence instead the beginning of the next past the "hole". Many ways to skin the cat... :)

More Answers (1)

Matt J
Matt J on 29 Mar 2021
Edited: Matt J on 29 Mar 2021
Of course, my condition is different but this is the same flow of question.
No, the solution will very much depend on the rule for filling the gaps. Here is one way to implement your example loop-free:
A = [4 6 7 8 9 13 15 20];
F=griddedInterpolant(A,A);
result=F(1:max(A))
result = 1×20
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  1 Comment
dpb
dpb on 29 Mar 2021
Edited: dpb on 29 Mar 2021
+1 for the specific rule.
Hopefully the looping construct will facilitate dealing with different infill rules.

Sign in to comment.

Categories

Find more on Creating and Concatenating Matrices in Help Center and File Exchange

Products


Release

R2020b

Community Treasure Hunt

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

Start Hunting!