Clear Filters
Clear Filters

Merging adjacent cells in a cell array and applying rules to remove entries

2 views (last 30 days)
I have a cell array with cells of different sizes, for instance:
([-2, -1], [1, -2]; [1, -2], [2]; [1, -2, -1], [1, 2]). I would like to merge the cells in each row, so that I get:
([-2, -1, 1, -2]; [1, -2, 2]; [1, -2, -1, 1, 2]).
I would then like to perform an operation where, within each cell, if two consecutive numbers are equal in size but opposite in sign then they are both removed, e.g. [-2, -1, 1, -2] becomes [-2, -2], and [1, -2, -1, 1, 2] becomes [1, -2, 2], then becomes [1] (through a double application of this operation). So, my final cell array becomes: ([-2, -2]; [1]; [1]).
Any suggestions on how to accomplish these feats?

Answers (3)

Benjamin
Benjamin on 16 Aug 2016
I'm sure there is a more efficient way, but this gets the job done:
a = {[-2, -1], [1, -2]; [1, -2], [2]; [1, -2, -1], [1, 2]};
output = cell(1);
% go thru each row of cell array
for iRow = 1:size(a,1)
% covert row to numerical array
temp = cell2mat(a(iRow,:));
flag = true;
while flag
Break = false;
% go thru each element
for iNum = 1:length(temp)
num = temp(iNum);
% see if there is a match
toRemove = find(temp == -num);
if ~isempty(toRemove)
% remove the matched elements
toRemove = [iNum,toRemove];
temp(toRemove) = [];
% need to get out of for loop since temp size has changed
Break = true;
break
end
end
if Break
continue
end
% store corrected array
output(end+1,1) = {temp};
flag = false;
end
end
output = output(2:end);
  6 Comments
Stephen23
Stephen23 on 16 Aug 2016
Edited: Stephen23 on 16 Aug 2016
Guillaume: but it does not provide the correct output: "my final cell array becomes: ([-2, -2]; [1]; [1])"
>> filtereda{:}
ans =
-2 -2
ans =
1
ans =
1 -2 2
See my answer for simple code that provides the correct output.
Guillaume
Guillaume on 16 Aug 2016
Stephen, you must have missed my new comment which fixed the problem (and is essentially the same as your answer)

Sign in to comment.


Bhavesh Bhatt
Bhavesh Bhatt on 16 Aug 2016
I hope this is what you are looking for -
cell1 = {[-2,-1],[1, -2]; [1 -2], [2]; [1,-2, -1],[1,2]};
no_of_iterations = 2;
[r c] = size (cell1);
for i = 1:r
cell1{i,1} = [ cell1{i,1:c}] ; % Combine the elements
end
cell1(:,2:end) = []; % Delete the unwanted columns
for k = 1:no_of_iterations
c1 = cellfun('length',cell1);
for j = 1:r
i = 1;
while(i<c1(j))
if (cell1{j,1}(i).*(-1)) == (cell1{j,1}(i+1))
cell1{j,1}(i+1) = [];
cell1{j,1}(i) = [];
c1(j) = c1(j) - 2;
end
i = i + 1 ;
end
end
end
  1 Comment
Benjamin
Benjamin on 16 Aug 2016
Edited: Benjamin on 16 Aug 2016
this works but is about 5x slower than my solution on my machine. doesn't matter for such a small array.

Sign in to comment.


Stephen23
Stephen23 on 16 Aug 2016
Edited: Stephen23 on 16 Aug 2016
This actually provides the requested output:
C = {[-2,-1], [1,-2]; [1,-2], [2]; [1,-2,-1], [1,2]};
D = cellfun(@(c)[c{:}],num2cell(C,2),'UniformOutput',false);
fun = @(v)abs(diff(sign(v)))==2 & diff(abs(v))==0;
for k = 1:numel(D)
idx = fun(D{k});
while any(idx)
D{k} = D{k}([true,~idx]&[~idx,true]);
idx = fun(D{k});
end
end
and the output:
>> D{:}
ans =
-2 -2
ans =
1
ans =
1
EDIT if speed is important, then without cellfun will be faster:
C = {[-2,-1], [1,-2]; [1,-2], [2]; [1,-2,-1], [1,2]};
D = cell(size(C,1),1);
fun = @(v)abs(diff(sign(v)))==2 & diff(abs(v))==0;
for k = 1:numel(D)
D{k} = [C{k,:}];
idx = fun(D{k});
while any(idx)
D{k} = D{k}([true,~idx]&[~idx,true]);
idx = fun(D{k});
end
end

Categories

Find more on Programming Utilities in Help Center and File Exchange

Products

Community Treasure Hunt

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

Start Hunting!