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

1 visualizzazione (ultimi 30 giorni)
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?

Risposte (3)

Benjamin
Benjamin il 16 Ago 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 Commenti
Stephen23
Stephen23 il 16 Ago 2016
Modificato: Stephen23 il 16 Ago 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 il 16 Ago 2016
Stephen, you must have missed my new comment which fixed the problem (and is essentially the same as your answer)

Accedi per commentare.


Bhavesh Bhatt
Bhavesh Bhatt il 16 Ago 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 Commento
Benjamin
Benjamin il 16 Ago 2016
Modificato: Benjamin il 16 Ago 2016
this works but is about 5x slower than my solution on my machine. doesn't matter for such a small array.

Accedi per commentare.


Stephen23
Stephen23 il 16 Ago 2016
Modificato: Stephen23 il 16 Ago 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

Prodotti

Community Treasure Hunt

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

Start Hunting!

Translated by