Reputation: 2511
I want to merge structure fields in case I do partial computations, to later fill up the whole structure field cells.
The results are put into cells according to index into the cell, like this:
for i=3:4;
results1.index{i}=i;
results1.sqr{i}=i*i;
end
for i=1;
results2.index{i}=i;
results2.sqr{i}=i*i;
end
giving, respectively:
results1 =
index: {[] [] [3] [4]}
sqr: {[] [] [9] [16]}
results2 =
index: {[1]}
sqr: {[1]}
is there a way to merge the resulting structures to obtain
allresults.index={[1] [] [3] [4]}
allresults.sqr={[1] [] [9] [16]}
I can avoid overlapping results, so no conflict resolution or overwriting in case of conflicting values (e.g. none of the cells are empty) would be ok. Please note that in the larger dataset, cells are not limited to scalars but may contain cells or other types.
Upvotes: 2
Views: 192
Reputation: 2511
Both answers work. So I took the simplicity of Mohsen with the one-step approach of David and combined:
function C = structCat2(A,B)
F=fieldnames(A);
for k = 1:numel(F),
f = F{k};
IA = ~cellfun('isempty',A.(f));
IB = ~cellfun('isempty',B.(f));
C.(f)(IA) = A.(f)(IA);
C.(f)(IB) = B.(f)(IB);
end
Upvotes: 1
Reputation: 9864
You can first write a small helper function to merge the cells:
function R = mergeCells(A,B)
R = {};
IA = ~cellfun('isempty',A);
IB = ~cellfun('isempty',B);
R(IA) = A(IA);
R(IB) = B(IB);
end
and then call it in a loop to merge the fields
for k = 1:numel(F),
f = F{k};
allresults.(f) = mergeCells(results1.(f), results2.(f));
end
Upvotes: 5
Reputation: 8459
Here's a function to accomplish this. I think it is fairly general, and it does deal with strings but does assume no conflicts. It will fail if the struct
's have different field names or a different number of fields. I can't tell you anything about performance or whether there are better ways to do this.
function T = structCat(re1,re2)
F=fieldnames(re1);
for i=1:length(F) %// Do one field name at a time
t1=re1.(F{i}); %// These are the individual cell arrays we are combining
t2=re2.(F{i});
if length(t2)>length(t1)
%// This loop just makes t1 be the longest cell array, it's a bit messy though
t1a=t1;
t1=t2;
t2=t1a;
end
T.(F{i})=t1; %// Now we know t1 is longer, set the new array to t1 initially
for j=1:length(t2) %// Do each element of t2 individually
if ~exist(T.(F{i}){j},'var') %// see if there is an element of t2 to insert into T
T.(F{i}){j}=t2{j}; %// if there is, insert it!
end
end
end
end
Usage is, for example,
for i=3:4;
re1.index{i}=i;
re1.index2{i}=i^2;
re1.strings{i}='dafsd';
re1.mat{i}=[i;2*i;3*i];
end
for i=1;
re2.index{i}=i;
re2.index2{i}=i^2;
re2.strings{i}='hmmm';
re2.mat{i}=[i;2*i;3*i].^2;
end
T=structCat(re1,re2)
which results in
T =
index: {[1] [] [3] [4]}
index2: {[1] [] [9] [16]}
strings: {'hmmm' [] 'dafsd' 'dafsd'}
mat: {[3x1 double] [] [3x1 double] [3x1 double]}
You should also check out this question and this entry in the Matlab File Exchange, although I think they do slightly different things.
Upvotes: 2