Dynamically adding elements into an array every nth element based on user-defined inputs, while preserving array order

조회 수: 25 (최근 30일)
Let's say I have a folder with an object sequence, and I want to copy/paste this object sequence into a new subfolder - but, I also want to insert copies of an arbitrary object into this sequence every nth object, where n is supplied by the user. Additionally, the naming schema has to be updated such that these inserted object stay in place, and we're not inadvertently deleting any objects from the original sequence.
In principal, the problem might look something like this:
OG_Sequence = [ 1 2 3 4 5 6 ] ; % original sequence
insertion_ratio = 2 ; % insert every "#" times
insertion_obj = "X" ; % this is an arbitrary object
New_Sequence = [ 1 2 X 3 4 X 5 6 X ] ; % this is what we want, with everything named in ascending order.
Where length(New_Sequence) = length(Old_Sequence) + length(Old_Sequence)/insertion_ratio. Above is 9, because 6 + 6/2 = 9. You can see how this might change depending on the length of the original (OG) sequence and/or the insertion ratio, e.g.:
OG_Sequence = [ 1 2 3 4 5 6 ] ;
insertion_ratio = 1 ;
insertion_obj = "X" ;
New_Sequence = [ 1 X 2 X 3 X 4 X 5 X 6 X ] ;
or:
OG_Sequence = [ 1 2 3 4 5 6 7 8 9 ] ;
insertion_ratio = 3 ;
insertion_obj = "X" ;
New_Sequence = [ 1 2 3 X 4 5 6 X 7 8 9 X ] ;
I've already got code written to get the user to supply the location of the object sequence, and copy those files over into a new subfolder... but I'm getting mired in edge-cases (how to handle evens/odds, what to do when the insertion_ratio==1, etc.), and above all, how to approach this dynamically and neatly.
So far I've got switch/case statements, as well as mod() statements, but I'm not having any luck in getting the output I want:
New_Sequence(1) = Old_Sequence(1) % Starts with the original, always
switch insertion_ratio
case insertion_ratio == 1 % Edge-case: where ratio = 1
m = 1 ;
for n = 2 : 2 : length(New_Sequence)
New_Sequence(n) = insertion_object ;
end
for n = 3 : 2 : length(New_Sequence)
New_Sequence(n) = Old_Sequence(n - m) ;
m = m + 1 ;
end
otherwise
for n = 2 : length(New_Sequence)
if mod(n, insertion_ratio) == 0
New_Sequence(n) = insertion_obj ;
else
New_Sequence(n) = Old_Sequence(n) ; % ?????????
end
end
end
The above works for the edge-case where the insertion_ratio = 1, but... that's it. I'm kind of stuck on how to move forward. I realize the problem is pretty vague, but that's because I'm trying not to clutter the post more than it already is.
Thanks!

채택된 답변

Jan
Jan 2018년 2월 27일
편집: Jan 2018년 2월 27일
data = [ 1 2 3 4 5 6 ] ;
n = 1; % Step width
x = -1; % To insert
len = numel(data);
result = [data; nan(1, len)];
result(2, n:n:len) = x;
result = result(~isnan(result)).';
This appends an additional row with NaNs and inserts the value in the wanted locations. Then the remaining NaNs are removed and the matrix elements are joined to a vector.
result = [data; nan(1, len)];
[1 2 3 4 5 6;
NaN NaN NaN NaN NaN NaN]
result(2, n:n:len) = x;
[1 2 3 4 5 6;
x NaN x NaN x NaN]
Now the NaNs are removed. The logical indexing processes the matrix
in columnwise order.
result(~isnan(result))
[1 x 2 x 3 x 4 x 5 x 6]

추가 답변 (1개)

Andrei Bobrov
Andrei Bobrov 2018년 2월 27일
S = 1:7; % original sequence
ir = 2 ; % insert every "#" times
io = 9999; % io this is an arbitrary object
%New_Sequence = [ 1 2 X 3 4 X 5 6 X ] ;
S = [S(:);nan(mod(-numel(S),ir),1)];
Sn = reshape(S,ir,[]);
Sn = [Sn;repmat(io,1,size(Sn,2))];
out = Sn(~cumsum(isnan(Sn)))
  댓글 수: 1
Jan
Jan 2018년 2월 28일
+1. I thought twice about the meaning of ~cumsum(isnan(x)). I even tried, if this is a typo and cumsum(~isnan(x)) was meant, but then I saw it. Thanks, it is nicer than
1:find(isnan(x(:)), 1, 'first')

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

카테고리

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

Community Treasure Hunt

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

Start Hunting!

Translated by