function [into] = grow_struct(into,from)

% Adds the entries from struct FROM into struct INTO. % % [INTO] = GROW_STRUCT(INTO,FROM) % % This function is designed for aggregating the behavioral % data from multiple subjects into one big struct. Each % subject’s data must be stored in an identically-arranged % struct. The fields in my data are all vectors, and within % a struct, they should all be of the same length. If that’s % not the case, this will error. % % INTO (in) - this is the struct into which all the values % from FROM will be copied. It should have all the same % number of fields as FROM. The only exception to this is if % this is the first time you’ve called this function - in % that case, INTO can be [], and it will automatically % create empty fields for it, based on FROM’s fieldnames. % % INTO (returned) contains the enlarged INTO struct, each of % whose fields should now have FROM’s contents % concatenated. % % UPDATE: this appears to work nicely, even for cell arrays, % though I hadn’t expected it to. I think this is because % ISVECTOR actually includes 1D cell arrays as vectors % too. Bonus. The unit test is reasonably complete.

if ~isstruct(from) error(‘FROM must be a struct’) end fnames = sort(fieldnames(from)); nFieldnames = length(fnames);

% if INTO is [], populate it with empty fields if isempty(into) for f=1:nFieldnames cur_fname = fnames{f}; into.(cur_fname) = []; end % f end % isempty

if ~isstruct(into) error(‘INTO must be a struct’) end into_f = sort(fieldnames(into));

% check that all the fields are the same - this also % requires that none are missing from one or the other if ~isequal(into_f,fnames) error(‘Both structs must contain the same fields’) end

if ( … ~check_all_fields_have_same_length(into) | … ~check_all_fields_have_same_length(from) … ) error(‘All the fields in the struct must have the same length’) end

for f=1:nFieldnames

cur_fname = fnames{f};

% overwrite the current field in INTO with the % concatenation of itself and the FROM field into.(cur_fname) = [into.(cur_fname) from.(cur_fname)];

end % f

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [success] = check_all_fields_have_same_length(s)

% S is a STRUCT. This just goes through all the fields in S, % and compares their length to one another. If they’re all % the same length, SUCCESS is true. % % Also, checks that all the fields are vectors.

success = true;

fnames = fieldnames(s); nFields = length(fnames);

% if there’s only one field, then there’s no way it can be % of different length to itself if nFields<2 return end

% get the length of the first field fname_1 = fnames{1};

% check that the first field is a vector. allow it to be [] % though if ~isvector(s.(fname_1)) & ~isempty(s.(fname_1)) success = false; end

% store the length of the first field, so that we can % compare all the other fields to it len_f1 = length(s.(fname_1));

% loop over the remaining fields for f=2:nFields

cur_fname = fnames{f};

% check that the current field is a vector, or [] if ~isvector(s.(cur_fname)) & ~isempty(s.(fname_1)) success = false; end

% check the length of the current field against the first % one if length(s.(cur_fname)) ~= len_f1 success = false; return end % comparing with len_f1

end % nFields

if ~success keyboard end

Home - Blog - Startups - Software - Research - Writing

Email me - updated 31 Dec 2012