Any simple way to change a struct with fields of length "n" to a st... (2024)

19 views (last 30 days)

Show older comments

Art on 11 Mar 2016

  • Link

    Direct link to this question

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n

  • Link

    Direct link to this question

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n

Commented: Kelly Kearney on 12 Mar 2016

Open in MATLAB Online

I have 2 structs each containing a field called 'time', along with other differently named fields of length "n"

i.e.

Mystruct.time = [1 4 6 8 9]

Mystruct.field2 = [5 6 7 8 9]

Mystruct.field3 = [23 423 2 4 7]

Yourstruct.time = [3 7]

Yourstruct.fieldX = [5 6]

What I need to do is create a time ordered "orderedStruct" that contains each index of these two structs, ordered by their time fields.

e.g. in this example I could type in "orderedStruct(num)" and could get the result:

orderedStruct(1) = struct with fields 'time' = 1, 'field2' = 5; 'field3' = 23;

orderedStruct(2) = struct with fields 'time' = 3, 'fieldX' = 5

orderedStruct(7) = struct with fields 'time' = 9, 'field2' = 9; 'field3' = 7;

Is there an efficient way to do this? I can imagine putting everything in a nested loop, from 1:number of structs and within that loop another going from 1:number of fields, but my structs could have 300 fields, with length of 50,000 or more. This would be a huge time hog.

Any ideas?

Thanks in advance

5 Comments

Show 3 older commentsHide 3 older comments

Image Analyst on 11 Mar 2016

Direct link to this comment

https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349464

  • Link

    Direct link to this comment

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349464

I don't understand how the 2nd and 7th structure were generated.

And what fields would orderedStruct(3), orderedStruct(4), orderedStruct(5), and orderedStruct(6) have?

Art on 11 Mar 2016

Direct link to this comment

https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349603

  • Link

    Direct link to this comment

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349603

Edited: Art on 11 Mar 2016

basically, I need to merge two different structs together based on time (which is a field that both have), creating a 1xN array of structs.

In the preceding example the 2nd orderedStruct index is the first index of each field of Yourstruct (I want the combined times to progress in the order: 1,3,4,6,7,8,9; i.e. the ordered times from both structs combined)

Or, perhaps an easier way of looking at it, I want to turn both structs from struct.field(1xN) to struct(1xN).field, then merge them together ordered by time.

Jos (10584) on 11 Mar 2016

Direct link to this comment

https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349607

  • Link

    Direct link to this comment

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349607

Guillaume on 11 Mar 2016

Direct link to this comment

https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349608

  • Link

    Direct link to this comment

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349608

Note that in an array of structure, all structures must have the same fields, so in your example orderedStruct must also have field2 and field3. What value should these be?

Art on 11 Mar 2016

Direct link to this comment

https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349616

  • Link

    Direct link to this comment

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349616

Open in MATLAB Online

After much searching and some therapy, this code will do what I want, however it takes WAY too long for what I need. It appears to create an array of the two starting structs (that contain different fields), although I may not be clear on that part:

Mystruct.time = [1 4 6 8 9];

Mystruct.field2 = [5 6 7 8 9];

Mystruct.field3 = [23 423 2 4 7];

Yourstruct.time = [3 7];

Yourstruct.fieldX = [5 6];

allStructs = {'Mystruct' 'Yourstruct'};

totind = 0;

for ind = 1:2

thisStruct = eval(char(allStructs(ind)));

fn = [rot90(fieldnames(thisStruct))]';

nItems = numel(thisStruct.(fn{1})); %%all fields are same length

sf=fn';

sf(2,1:numel(fn))={{}};

sf = sf(:)';

S=struct(sf{:});

for f=1:numel(fn)

for n = 1:nItems %%nItems: -1 : 1;

S(n).(fn{f}) = thisStruct.(fn{f})(:,n);

end

end

%%include struct "S" into "all_messages" and "all_times".

%%"all_times" is used to sort the cell array "all_messages".

for ind = 1:numel(S)

totind = totind + 1;

all_messages(totind) = {S(ind)};

all_times(totind) = S(ind).time;

end

end

[~,msg_order] = sort(all_times);

ordered_msgs = all_messages(msg_order);

Typing ordered_msgs{1} gives a struct with fields time, field2 and field3, typing ordered_msgs{2} gives a struct with time and fieldX.

Any way to make this faster?

Sign in to comment.

Sign in to answer this question.

Answers (3)

Jos (10584) on 11 Mar 2016

  • Link

    Direct link to this answer

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#answer_213233

  • Link

    Direct link to this answer

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#answer_213233

This question clearly shows how not thinking about your data management in the beginning will get you into trouble later on.

What do you want to have as the value of a field for which there is no time point ...?

3 Comments

Show 1 older commentHide 1 older comment

Stephen23 on 11 Mar 2016

Direct link to this comment

https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349623

  • Link

    Direct link to this comment

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349623

+1 I would give ten points if I could.

Why do people only start to think about data management once the bugs start appearing?

Art on 11 Mar 2016

Direct link to this comment

https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349631

  • Link

    Direct link to this comment

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349631

Edited: Art on 11 Mar 2016

Well, thanks for the feedback but let me clarify. I inherited two very usable structs which are, in fact, separate messages that are normally handled as separate entities. Because there are some fields common to both (not indicated in this example), it would be very handy for me to incorporate them into one time-ordered variable for plotting and analysis.

Just looking for an easy way of doing this.

Art on 11 Mar 2016

Direct link to this comment

https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349642

  • Link

    Direct link to this comment

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349642

BTW Jos, the messages are based on time. If there is no time at a particular index, there won't be that index point in any field.

Sign in to comment.

Guillaume on 11 Mar 2016

  • Link

    Direct link to this answer

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#answer_213258

  • Link

    Direct link to this answer

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#answer_213258

Open in MATLAB Online

Regarding your latest comment, there is of course a simpler way to achieve the same thing, without eval and only looping once over the structures:

MyStruct = struct('Time', [1 4 6 8 9], 'field2', [5 6 7 8 9], 'field3', [23 423 2 4 7]);

YourStruct = struct('Time', [3 7], 'fieldX', [5 6]);

allstructs = {MyStruct, YourStruct}; %store structures in a cell array so we can iterate over them.

reshapedstructs = cell(size(allstructs));

timings = cell(size(allstructs));

%transform each struct from a struct of arrays into an array of structs of scalars

for sidx = 1:numel(allstructs)

fn = fieldnames(allstructs{sidx});

svalues = cell2mat(struct2cell(allstructs{sidx}));

reshapedstruct = cell2struct(num2cell(svalues), fn, 1); %the vertcat will fail if fields of the struct have different size

reshapedstructs{sidx} = num2cell(reshapedstruct'); %split the array of structs into a row cell array of scalar struct

timings{sidx} = allstructs{sidx}.Time;

end

%flatten the cell arrays and reorder by timing

reshapedstructs = [reshapedstructs{:}];

timings = [timings{:}];

[~, order] = sort(timings);

reshapedstructs = reshapedstructs(order);

celldisp(reshapedstructs)

A similar way to achieve the same in even less lines of code, but probably slower:

allstructs = {MyStruct, YourStruct};

reshapedstructs = cellfun(@(s) num2cell(cell2struct(num2cell(cell2mat(struct2cell(s))), ...

fieldnames(s), 1)'), allstructs, ...

'UniformOutput', false);

timings = cellfun(@(s) s.Time, allstructs, 'UniformOutput', false);

reshapedstructs = [reshapedstructs{:}];

timings = [timings{:}];

[~, order] = sort(timings);

reshapedstructs = reshapedstructs(order);

celldisp(reshapedstructs)

0 Comments

Show -2 older commentsHide -2 older comments

Sign in to comment.

Kelly Kearney on 11 Mar 2016

  • Link

    Direct link to this answer

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#answer_213260

  • Link

    Direct link to this answer

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#answer_213260

Open in MATLAB Online

How about this?

A.time = [1 4 6 8 9];

A.field2 = [5 6 7 8 9];

A.field3 = [23 423 2 4 7];

B.time = [3 7];

B.fieldX = [5 6];

t = unique([A.time, B.time]);

[tf1,loc1] = ismember(A.time, t);

[tf2,loc2] = ismember(B.time, t);

flds = unique([fieldnames(A); fieldnames(B)]);

data = nan(length(flds), length(t));

for ii = 1:length(flds)

if isfield(A, flds{ii})

data(ii,loc1) = A.(flds{ii});

end

if isfield(B, flds{ii})

data(ii,loc2) = B.(flds{ii});

end

end

data = num2cell(data);

C = cell2struct(data, flds, 1);

You didn't specify how you wanted missing values or duplicated times to be treated. So in this example, times without a field value are indicated by NaNs, and any time that has data in both structures simply uses the data from the second one.

2 Comments

Show NoneHide None

Art on 11 Mar 2016

Direct link to this comment

https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349665

  • Link

    Direct link to this comment

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349665

Open in MATLAB Online

Thanks to both you, Kelly, and Guillaume for great help. Let me add one more wrinkle: if there were one field with char instead of num, could your examples work with this?

e.g, in your example Kelly, if

A.field2 = [{'blah'} {'blah'} {'xxxx'} {'yyyy'} {'zzzzz'}];

Kelly Kearney on 12 Mar 2016

Direct link to this comment

https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349709

  • Link

    Direct link to this comment

    https://matlabcentral.mathworks.com/matlabcentral/answers/272695-any-simple-way-to-change-a-struct-with-fields-of-length-n-to-a-struct-of-length-n#comment_349709

No, it would need to be modified a bit. Instead of preallocating data with NaNs, you'd need to set it up as a cell array, and add in a few num2cell's when assigning the numeric arrays to it. I'm away from my computer right now but I'll try to post a modified version later.

Sign in to comment.

Sign in to answer this question.

See Also

Categories

MATLABLanguage FundamentalsData TypesStructures

Find more on Structures in Help Center and File Exchange

Tags

  • struct indexing

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

An Error Occurred

Unable to complete the action because of changes made to the page. Reload the page to see its updated state.


Any simple way to change a struct with fields of length "n" to a st... (15)

Select a Web Site

Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .

You can also select a web site from the following list

Americas

  • América Latina (Español)
  • Canada (English)
  • United States (English)

Europe

  • Belgium (English)
  • Denmark (English)
  • Deutschland (Deutsch)
  • España (Español)
  • Finland (English)
  • France (Français)
  • Ireland (English)
  • Italia (Italiano)
  • Luxembourg (English)
  • Netherlands (English)
  • Norway (English)
  • Österreich (Deutsch)
  • Portugal (English)
  • Sweden (English)
  • Switzerland
    • Deutsch
    • English
    • Français
  • United Kingdom(English)

Asia Pacific

Contact your local office

Any simple way to change a struct with fields of length "n" to a st... (2024)
Top Articles
Latest Posts
Article information

Author: Aracelis Kilback

Last Updated:

Views: 6383

Rating: 4.3 / 5 (64 voted)

Reviews: 95% of readers found this page helpful

Author information

Name: Aracelis Kilback

Birthday: 1994-11-22

Address: Apt. 895 30151 Green Plain, Lake Mariela, RI 98141

Phone: +5992291857476

Job: Legal Officer

Hobby: LARPing, role-playing games, Slacklining, Reading, Inline skating, Brazilian jiu-jitsu, Dance

Introduction: My name is Aracelis Kilback, I am a nice, gentle, agreeable, joyous, attractive, combative, gifted person who loves writing and wants to share my knowledge and understanding with you.