Create empty rows in a cell, based in a condition

45 views (last 30 days)
Happy Bear
Happy Bear on 3 Feb 2020
Commented: Happy Bear on 4 Feb 2020
Hello everyone,
I have a cell (390x1) and it should repeat the words 'hello, 'hey', 'hi' and 'hoi' every 4 rows, as in the following:
Row 1 - 'hello'; Row 2 - 'hey'; Row 3 - 'hi'; Row 4 - 'hoi'; Row 5 - 'hello'; Row 6 - 'hey'; Row 7 - 'hi'; Row 8 - 'hoi'.
However, sometimes it goes like:
Row 9 - 'hello'
Row 10 - 'hey'
Row 11 - 'hoi'
And it skips the 'hi' row, making it so that I can't loop it using something like "for i = 1:4:390", which is what I need.
What I want to do is create the same cell where the "3rd row" of every "4 rows" is empty, that is: when the 3rd row has "hi" in it, those 4 rows stay the same. But when the "hi" row is missing, it creates an empty cell row between the 2nd and the 4th row (between the 'hey' and the 'hoi').
For example, it would be come:
Row 9 - 'hello'
Row 10 - 'hey'
Row 11 - ' ' (empty)
Row 12 'hoi'
I already tried doing this with loops and the strcmp function, but I really can't do it.
Please ask questions in case I didn't explain myself well enough.
Thank you

Accepted Answer

Guillaume on 3 Feb 2020
Edited: Guillaume on 3 Feb 2020
Here's an efficient way, with a loop (cellfun) only over the missing elements, not the whole cell array. In addition if several contiguous entries are missing, it will have the required number of empty cells.
fillvalue = ''; %whatever you want to be put in the missing entries
valueset = {'hello', 'hey', 'hi', 'hoi'}; %the repeating set. Must be in the correct order!
%dataset: the cell array containing repeatition of valueset in the same order, but with some values missing
dataset = valueset(repmat(1:numel(valueset), 1, 5))'; dataset([8, 9, 12, 19]) = []; %demo dataset with 4 missing entries
%The following requires dataset to be a COLUMN cell vector.
[found, id] = ismember(dataset, valueset); %replace char vectors by numeric id (corresponding to their order in value set)
assert(all(found), 'dataset contains value not present in value set. Cannot continue');
deltaid = mod(diff(id), numel(valueset)); %complete difference between ids. If no entry is missing it should be all 1s.
%Non 1 entries in deltaid is where some elements are missing. The values of deltaid minus 1 indicates how many entries are missing
ismissing = deltaid ~= 1;
splitdataset = mat2cell(dataset, diff([0; find(ismissing); numel(dataset)])); %split cell array at locations where entries are missing. mat2cell despite its name also works with cell arrays
splitdataset = [splitdataset, arrayfun(@(nummissing) repmat({fillvalue}, nummissing, 1), [deltaid(ismissing)-1; 0], 'UniformOutput', false)]'; %append split data with appropriate number of missing marker and transpose
newdataset = vertcat(splitdataset{:})
%entries 8, 9, 12, 19 will have had fillvalues inserted
Note that this code will detect any missing element in the sequence, not just the 'hi', work for any length of input, for whatever text is in the set, and regardless of how many elements are missing.
  1 Comment
Happy Bear
Happy Bear on 4 Feb 2020
This did exactly what I needed it to do! Thank you so much.

Sign in to comment.

More Answers (1)

Constantino Carlos Reyes-Aldasoro
I do not know why there should be rows that are skipped, unless you are copying and pasting and something goes wrong. I have been able to do what you wanted like this:
>> for k=1:4:390
Notice that to have the answer as rows you have to specify the column {k,1} otherwise the default will fill a value per column. Now if you want to have a blank space you can do it like this:
>> for k=1:4:390
I hope that this answers your question, if it does not, let me know. If it does, please accept the answer.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!