File Exchange Pick of the Week

April 22nd, 2008

MATLAB Basics: Array of structures vs Structures of arrays

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

Video Content

iconFiles.jpgiconPod.jpg

20 Responses to “MATLAB Basics: Array of structures vs Structures of arrays”

  1. Emil replied on :

    It’s easier to create vector s by:
    s = [people.SimmNum];

  2. Tom replied on :

    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]

  3. Doug replied on :

    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

  4. Ryan Gray replied on :

    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{:};

  5. liuzhi replied on :

    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?

  6. Doug replied on :

    You want to use a cell array here:

    
    s{1} = s0
    s{2} = s1
    s{1}.field1
    s{1}.field1(1,3)
    

    Doug

  7. Dan replied on :

    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.

  8. Sandy replied on :

    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

  9. Doug replied on :

    @Sandy,

    What do you mean by “unpack” the components?

    Doug

  10. Halfdan replied on :

    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.

  11. Doug replied on :

    @hakdan,

    I do not understand your question. What have you tried?

    Doug

  12. Emil replied on :

    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

  13. Doug replied on :

    @Emil,

    Shy not just save it? Why are you trying to pull them out of the structure?

    Doug

  14. Huw replied on :

    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.

  15. annon replied on :

    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?

  16. Doug replied on :

    @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

  17. Steve L replied on :

    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.

  18. Omar replied on :

    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

  19. nick replied on :

    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

  20. Paul Torek replied on :

    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?

Leave a Reply

Wrap code fragments inside <pre> tags, like this:

<pre class="code">
a = magic(3);
sum(a)
</pre>

If you have a "<" character in your code, either follow it with a space or replace it with "&lt;" (including the semicolon).


MathWorks

Brett & Jiro share their favorite user-contributed submissions from the File Exchange.

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