File Exchange Pick of the Week

MATLAB Basics: Array of structures vs Structures of arrays 26

Posted by Doug Hull,

This short video covers the difference between a “structure of arrays” and an “array of structures”.

Video Content

iconFiles.jpgiconPod.jpg

26 CommentsOldest to Newest

This and Emil’s comment were quite helpful to me.

To take this one step further, one advantage of Arrays of Structures would be the ability to have vectors of different lengths for each numerical part, and a cell array of names of different lengths for each name part.

For example:

people(1).name=’Erin’
people(2).name={‘Joan’ ‘Carla’}
people(1).sim=44
people(2).sim=[561 49]

Emil,

Yes, you are correct. I can not believe I over looked that. There are so many ways to do certain things in MATLAB.

Doug

If you have an array that you want to assign to a field across a structure array, you can do this:

[structArray(:).fieldname] = deal(num2cell(array))

Of course, the length of array should be the same as the length of structArray, but if structArray doesn’t exist yet, then you can do:

[structArray(1:length(array)).fieldname] = deal(num2cell(array))

If array is already a cell array, you can avoid using both deal and num2cell (although they will still work) and use:

[structArray(:).fieldname] = array{:}
or
[structArray(1:length(array)).fieldname] = array{:}

An example, modifying the struct array ‘people’ from the video:

names = {‘Larry’,'Moe’,'Curly’};
[people(:).name] = names{:};

In one of my program, I’d like to use an array of array of structures, such like

s0 = struct('field1', [v1 v2], 'field2', [v3 v4]);
s1 = struct('field1', [v1' v2'], 'field2', [v3' v4']);

I want another data structure s = [s0, s1] so that I can access s0(1) like s(0,1). How can I do that?

I may be wrong, but one of the examples in Post 4 (Ryan Gray) doesn’t work as advertised. Specifically,

[structArray(1:length(array)).fieldname] = deal(num2cell(array))

ends up assigning the whole array to every instance of fieldname, instead of distributing the array across those instances. What does seem to work is:

cell_array = num2cell(array);
[structArray(1:length(array)).fieldname] = cell_array{:};

I leave it as an exercise for a MATLAB guru to splain why this is the case.

Hi

I’m new at this –

How do I save an array of structures to a .mat file so that I can use it later? I’m able to “save” it and then “load” it into a different script, but not able to unpack the components.

Thanks,

Sandy

I would also like to know how to save an array of structures, rather than just a single structure. I know that there’s a memory waste connected with array of structs, but I really find array of struct to be a very easy way of organizing certain kinds of data.

Hei,

I ran into the same problem described by the previous two posts.

names = {'Peter','Paul','Mary'};
ages = {25,29,26};
[people(1:3).name] = names{:};
[people(1:3).age] = ages{:};

Now

save('test','-struct','people')

yields:
??? Error using ==> save
The argument to -STRUCT must be the name of a scalar structure variable.

whereas

person = people(1);
save('test','-struct','person')

is no problem.

The following would work

save('test','people')

but is very unhandy as

x = load('test');

makes x a 1×1 struct with field people, and would require additionally

x = x.people;

So the question is:
What is the best way to save a struct array?

Emil

by the way, if ages was a 1×3 double [25,29,26] and not a 1×3 cell:
How would I deal it across the struct array people? This is the same problem as adressed by Dan on Aug 4th

I also found the same problem with post 4 as described in post 7 and would be grateful if someone could explain why the solution needs to use 2 lines of code. e.g.

weather = repmat(struct('temp', 72, 'rainfall', 0.0),1,3);
nums = [23 10 12];
cellArray = num2cell(nums - [weather(:).temp])
[weather(:).rainfall] = cellArray{:}

Is there no way to assign each element of the result of num2cell to weather.rainfall on a single line.

Hi
I’ve come across your blog a few times and have found it very helpful. So let me begin by thanking you.

I have a small question that I’ve not been able to find the solution to online. I’m hoping you may be able to shed some light on the matter.

The following structure has 2 elements.

people = struct(...
'name',{'bob', 'john'},...
'numKids',{0, 2}, ...
'kidsage',{[],[12,9]});

each element people(1), people(2) has three frields (name, numKids, kidsage)

Instead of declaring the structure in one line as above, I would like to define it one field at a time.
The closest working example I’ve been able to come up with is

people = struct

people.('name') = {'bob, 'john'}
people.('numkids') = {0, 2}
people.('kidsage') = {[], [12, 9]}

But defined in this way, the people structure only has one element.
ie.

people(1) =

name: {'bob' 'john'}
numkids: {[0] [2]}
kidsage: {[] [12, 9]}

Any ideas?

@Annon,

I do not know of a way to do that. You seem to be able to get the data in in other ways, why is it important to do it in this particular manner?

Doug

Annon,

To do this you can use DEAL, but I think Doug’s question is a good one: why do you need/want to do it this way?

% Make sure people2 doesn't exist yet
% This way you can tell that the command performed
% the initial creation correctly
clear people2

% Define the cell array of names
S = {'bob', 'john'};

% DEAL the elements of the cell into the struct
[people2(1:2).name] = deal(S{:})

If you’re using release R14 or later, you can omit the DEAL as described in the Release Notes.

I want to have a .wav file into a vector so I can create de Spectra with the SPtool.

When I use the wavread() function and import the data into sptool it say thats an [array] so i couldnt create the spectrum, this tool only work with vectors. So how can i turn this array into vector?

a little help here please

hi
i am new in MATLAB, can u plz tell whats d problem with the following statements (i need to assign an array of integers to a member of an array of structures )
n(1).loc=[x-1 y+1];
n(2).loc=[x y+1];
n(3).loc=[x+1 y+1];
n(4).loc=[x+1 y];
n(5).loc=[x+1 y-1];
why are these assignments wrong?? plz reply ASAP… thnx

Thankyou thankyou thankyou!

You gave me the direction I needed to extract relevant info from the matlab dir filename command. Such as:

function Subdirs = OneLevelSubDirs(directory,match)
% xxx Need Help xxx
% Subdirs = OneLevelSubDirs(directory,match)

if nargin < 2 || isempty(match)
match = '*';
end

X = dir(directory);

Xdir = {X(:).name};
Xdir = Xdir(find(cell2mat({X(:).isdir})));
Subdirs = Xdir(~cellfun(@(x)ismember(x,{'.';'..'}),Xdir));

Did I mention thank you?

Hi I’ve been looking through your post but couldn’t find and answer to my problem, which resides in the “array of structures”- “structure of arrays” paradigm

I have the following text file containing exchange rates,

id code rate
1 Euro 1
2 HUF 0.0036
3 PZL 0.2532
4 CZK 0.0406
5 SKK 0.03319
6 BGN 0.5113

which I want to import into an “array of structures”, of the form

currency(1).id = 1
currency(1).code = ‘Euro’
currency(1).rate = 1
.
.
.
currency(6).id = 6
currency(6).code = ‘BGN’
currency(6).rate = 0.5113

Of course I’d like to avoid this manual work with for loops and instead create dynamicaly the structure fields using the file headers and populating the structure.

My immediate approach was first to read the file with textscan

fid = fopen(‘file.txt’)
names = textscan(fid,’%s %s %s’,1,’CollectOutput’,1);
values = textscan(fid,’%s %s %s’,'CollectOutput’,1);
fclose(fid)

thus generating two cell arrays. Secondly, I use the cell2struct function as

currency = cell2struct(content,headers{:},2)

which creates a “structure of arrays”

currency =
id: [6x1 uint32]
code: 1×1 cell array
rate: [6x1 double]

The indexing is the of the form

currency.id(1)
currency.code{1}

How could I then generate using the same reasoning an array of structures?

thanks

I have a question. How do I create a structure in order to initialize some parameters needed in other functions? If someone is interested in answering this question I will write him a part of the code.

Regards,
Octavian

For example my parameters should be initialize like this: in the first position of my structure I have a number, in the second position a number, in the third position a vector and so on till the 9th position.

Regards,
Octavian

Hi,
I am trying to merge two array of structure based on the common field security_ID. The last two lines does not seem to work. I want to assign the Return and ReturnDt column from T2 array into T1 array. It is possible that some security_id that are in T1 are not in T2 and vice-versa. I can do the assignment in the loop or use arrayfun but trying to do in one line of code.

ID1=[T1.Security_ID];
ID2=[T2.Security_ID];
[a,b,c]=intersect(ID1,ID2);
T1(b).Return=[T2(c).Return];
T1(b).ReturnDt=[T2(c).ReturnDt];

Hi.
while populating an array of structures, can I use such a syntax as
data(3:10).pin = [6 7];
I am getting an error while trying to use this. I hope it is clear as to what I want to achieve. Please let me know if there is a work around.

Thanks,
a.

This may be helpful to someone. I couldn’t find a built-in function or anything in the file exchange that does this.

function out=SoA2AoS(in)
%convert structure of arrays to an array of structures
%the lengths of the fields must be the same

% example:
% in.a=[1:5];
% in.b=[11:15];
% out=SoA2AoS(in)
% out(1)

fn=fieldnames(in);
c=struct2cell(in);

for i=1:length(fn)
d=num2cell(c{i});
m=num2str(length(d));
eval(['[out(1:' m ').' fn{i} ']=deal(d{:});’])
end

These postings are the author's and don't necessarily represent the opinions of MathWorks.