0

I have a struct array: a 1x10 struct array with fields: N, t, q, r, T, each of which is a vector of type double.
enter image description here

The 10 array entries each represent the outcome of a testing condition in an experiment. I would like to be able to make a function that takes two indices, index1 and index2, and modifies the constituent N, t, q, r vectors (T is a single number) so that they become length index1:index2. Something like

function sa = modifier(struct_array, index1, index2)
    sa = structfun(@(x) x(index1:index2), struct_array, 'UniformOutput', false)
    stuff
end

Now, where stuff is, I've tried using structfun and cellfun, see here except that those return a struct and a cell array, respectively, whereas I need to return a struct array.

The purpose of this is to be able to get certain sections of the experimental results, e.g. maybe the first five entries in each vector inside each cell correspond to the initial cycles of the experiment.

Please let me know if this is possible, and how I might go about it!

1 Answer 1

1

You can try this:

From this question's answer, I figured out how to loop through struct fields. I modified the code to address your question by extracting a subsample from each field that goes through the for loop and then copy the desired subset of that data into a new struct array with identically named fields.

% Define indexes for extraction
fieldsToTrim = {'a' 'b'};
idx = 2:3; % Create index vector for extracting selected data range

% Define test struct to be read
teststruct.a = [1 2 3];
teststruct.b = [4 5 6];
teststruct.c = [7 8 9];

% Get names of struct fields
fields = fieldnames(teststruct);

% Loop through each field and extract the subset
for i = 1:numel(fields)
    if max(strcmp(fields{i},fieldsToTrim)) > 0
        % If current matches one of the fields selected for extraction
        % extract subset
        teststructResults.(fields{i}) = teststruct.(fields{i})(idx);
    else
        % Else, copy all contents on field to resulting struct
        teststructResults.(fields{i}) = teststruct.(fields{i});
    end
end

Finally, to turn this into a function, you can modify the above code to this:

function teststructResults =  extractSubsetFromStruct(teststruct,fieldsToTrim,idx1, idx2)
    % idx1 and idx2 are the start and end indicies of the desired range

    % fieldsToTrim is a string array of the field names you want
    % included in the trimming, all other fields will be fully copied

    % teststruct is your input structure which you are extracting the
    % subset from

    % teststructResults is the output containing identically named
    % struct fields to the input, but only containing data from the selected range

    idx = idx1:idx2; % Create index vector for extracting selected data range

    % Get names of struct fields
    fields = fieldnames(teststruct);

    % Loop through each field and extract the subset
    for i = 1:numel(fields) 
        if max(strcmp(fields{i},fieldsToTrim)) > 0
            % If current matches one of the fields selected for extraction
            % extract subset
            temp = teststruct.(fields{i});
            teststructResults.(fields{i}) = temp(idx);
        else
            % Else, copy all contents on field to resulting struct
            teststructResults.(fields{i}) = teststruct.(fields{i});
        end
    end
end

I successfully ran the function like this:

teststruct = 

    a: [1 2 3]
    b: [4 5 6]
    c: [7 8 9]

>> extractSubsetFromStruct(teststruct,{'a' 'b'},2,3)

ans = 

    a: [2 3]
    b: [5 6]
    c: [7 8 9]
Sign up to request clarification or add additional context in comments.

7 Comments

I'm getting this error: Field reference for multiple structure elements that is followed by more reference blocks is an error.
hmm.. give me a minute, I'll retest the code and repost!
K, updated, and I made a few changes to the function.
The problem I'm getting is that teststructResults.(fields{i}) = teststruct.(fields{i})(idx) will not evaluate. Once the i-th fieldname is selected, teststruct.(fields{i}) is okay, because it returns all of the fields of that name in the struct, but it's not allowed to return the 2:4 elements of each of those.
Your most recent update that introduced an intermediate temp has done the trick for me. Thank you so very much, @James.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.