StamDad
StamDad

Reputation: 135

Manipulation of cell arrays

I have two cell arrays of size [1X5]

K= {} {O1,O2,O3,O4} {O1,O3} {O1,O2,O3,O4} {O1,O2,O3,O4}
W= {O3}{O2}{O2,O3}{O2,O4}{O4}

I want to get as a result a cell array named S of size [1X4] as follows :

I put the contents of K{i} in every S{j} where j are the indices of the contents of W{i} (for example the cell W{3} has as content O2 and O3 so j=2,3. I put the content of K{3} in the cells S{2} and S{3} ).

After that I add in every S{i} a content Oi and I eliminate redundancy in S.

The expected result is the following :

S={O1}{O1,O2,O3,O4}{O1,O3}{O1,O2,O3,O4}

Upvotes: 1

Views: 83

Answers (2)

rahnema1
rahnema1

Reputation: 15837

Here is a solution using accumarray and unique:

K= {{} ,{'O1','O2','O3','O4'} ,{'O1','O3'} ,{'O1','O2','O3','O4'} ,{'O1','O2','O3','O4'}};
W= {{'O3'},{'O2'},{'O2','O3'},{'O2','O4'},{'O4'}};


subs = sscanf(cell2mat([W{:}]),'O%d');
m = max(subs);
subs = [subs;(1:m).'];

vals = repelem(1:numel(W),cellfun(@numel,W));
vals = [vals numel(K)+1:numel(K)+m]

K = [K num2cell(cellstr(num2str((1:m).','O%d'))).'];
%If your data are string scalars use the following K
%K = [K num2cell(string(cellstr(num2str((1:m).','O%d')))).']

result = accumarray(subs,vals,[],@(x){unique([K{x}])})


result = 
{
  [1,1] = 
  {
    [1,1] = O1
  }
  [2,1] = 
  {
    [1,1] = O1
    [1,2] = O2
    [1,3] = O3
    [1,4] = O4
  }
  [3,1] = 
  {
    [1,1] = O1
    [1,2] = O3
  }
  [4,1] = 
  {
    [1,1] = O1
    [1,2] = O2
    [1,3] = O3
    [1,4] = O4
  }
}

Upvotes: 1

Dev-iL
Dev-iL

Reputation: 24169

You can use the union function for this as well as several loops:

function S = q47140074(K,W)
if nargin < 2
  % Input data:
  K = {"", ("O"+(1:4).').', ("O"+[1;3]).', ("O"+(1:4).').', ("O"+(1:4).').'};
  W = {"O3", "O2", ("O"+(2:3).').', ("O"+[2;4]).', "O4"};
end
% Preprocess data:
Wn = cellfun(@stripO,W,'UniformOutput',false);
% Preallocation:
S = num2cell(strings(1, max(cellfun(@max,Wn))));
% Computation:
for ind1 = 1:numel(Wn)
  tmpW = Wn{ind1};
  for ind2 = 1:numel(tmpW)
    S{tmpW(ind2)} = union(S{tmpW(ind2)}, K{tmpW(ind2)});
  end
end

for ind1 = 1:numel(S)
  S{ind1} = setdiff(union(S{ind1},"O" + ind1),"");
end

end

function out = stripO(in)
  out = str2double(strip(in,'left','O'));
end

Result:

Result2

Upvotes: 2

Related Questions