Borrar filtros
Borrar filtros

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

2 visualizaciones (últimos 30 días)
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?

Respuestas (3)

Benjamin
Benjamin el 16 de Ag. de 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 comentarios
Stephen23
Stephen23 el 16 de Ag. de 2016
Editada: Stephen23 el 16 de Ag. de 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 el 16 de Ag. de 2016
Stephen, you must have missed my new comment which fixed the problem (and is essentially the same as your answer)

Iniciar sesión para comentar.


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

Iniciar sesión para comentar.


Stephen23
Stephen23 el 16 de Ag. de 2016
Editada: Stephen23 el 16 de Ag. de 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

Categorías

Más información sobre Programming Utilities en Help Center y File Exchange.

Etiquetas

Productos

Community Treasure Hunt

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

Start Hunting!

Translated by