Clear Filters
Clear Filters

Converting a cell array of dissimilar structs to an array of structs

5 views (last 30 days)
In R2013b, say I have an cell array of structs like the following
% Some Mock Data
data{1} = struct('day', 'Monday', 'Temp', '35');
data{2} = struct('day', 'Tuesday', 'Temp', '34');
% Notice that data{3} has an extra field/value pair
data{3} = struct('day', 'Wednesday', 'Temp', '37', 'Comment', 'Rain');
I want to convert this into a struct array with 3 elements, but I want to "fill in" the missing field (Comment) in mystructarray(1) and mystructarray(2) with the empty array. Specifically, I want to end up with:
mystructarray(1)
ans =
day: 'Monday'
Temp: '35'
Comment: []
mystructarray(2)
ans =
day: 'Tuesday'
Temp: '34'
Comment: []
mystructarray(3)
ans =
day: 'Wednesday'
Temp: '37'
Comment: 'Rain'
I have tried the following, which is attractive for its readability, but it works ONLY if the 3 structures have the same field names.
mystructarray = [data{:}];
But because of the 'Comment' field in cell 3, I get the error:
Error using horzcat
Number of fields in structure arrays being concatenated do not match.
Concatenation of structure arrays requires that these arrays have the same set
of fields.
Is there an elegant way to build the desired structure array and "fill in" the missing fields to get what I want? I've tried CELLFUN but haven't gotten far with that function either.
Thank you. -Matt

Accepted Answer

Geoff Hayes
Geoff Hayes on 28 Aug 2014
Matthew - using your example, you could first try getting a list of all the unique fields from all structures of the cell array
>> uniqueFields = unique(char(cellfun(@(x)char(fieldnames(x)),data,...
'UniformOutput',false)),'rows')
uniqueFields =
Comment
Temp
day
With the above, we create a character array of all fields within each structure (using cellfun and *fieldnames), and then treat every row as a single entity, and find those that are unique.
Now with that we should be able to iterate through the cell array, and figure out which fields are missing
for k=1:length(data)
for u=1:size(uniqueFields,1)
fieldName = strtrim(uniqueFields(u,:));
if ~isfield(data{k}, fieldName)
data{k}.(fieldName) = [];
end
end
end
And so,
>> mystructarray = [data{:}]
mystructarray =
1x3 struct array with fields:
day
Temp
Comment
Try the above and see what happens!
  1 Comment
Matthew Crema
Matthew Crema on 28 Aug 2014
Edited: Matthew Crema on 28 Aug 2014
Short and clever solution.
It works perfectly with the example data set and also with my actual, much larger data structures (which do not contain nested structs).
Thanks!

Sign in to comment.

More Answers (0)

Categories

Find more on Structures 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!