Search code examples
arraysmatlabdictionaryoctaveprojection

How to create projection of a field of structures contained within vector in Matlab?


I want this (array = vector):

array.Select(elem => elem.my_field).ToArray(); // C# + Linq
array map _.my_field // Scala, I believe

In plain English, I have vector. Each element is structure. Each structure has field (of any kind). Now, instead of having this, I would like to have vector of "fields".

Example:

So, if initially I had vector of name+age structure (see below for update), I would like to create projection, so I end up with vector of ages (a sequence of ages).

I tried arrayfun function, but this gives me error:

error: cellfun: all values must be scalars when UniformOutput = true

I suspect this is environment settings, but I cannot switch those, because my code will be run in alien environment.

UPDATE: I oversimplified this example, I am sorry -- the age is a number, but from time to time it is a pair of numbers. So in general case, I have to assume it can be vector of numbers of any length (as I understand in Matlab a number is vector.length=1).

Question

How to make such "combined" projection in Matlab?


Solution

  • You can use cat to catenate your array:

    s = struct('age',{10 20 20},'name',{'Bob','Max','Peter'})
    1x3 struct array with fields:
        age
        name
    
    age = cat(1,s.age)
    age =
        10
        20
        20
    

    If you wanted to use arrayfun, you'd do the following:

    age = arrayfun(@(x)x.age,s);
    

    EDIT

    To catenate a structure whose fields are of unknown length, there are two options: If you just want all the "ages", and it doesn't matter that "age" #5 ends up at position 6, because there were two entries for "age" #2, you catenate along the dimension where all of your "age"-arrays have the same length. For example, if they're all 1x1 or 1x2 or 1x3 arrays etc., you write

    age = cat(2,s.age);
    

    If, alternatively, you want element #2 of your output array to have two entries (because s(2).age had two entries), you catenate into a CELL ARRAY

    age = {s.age};
    

    Each element of age (accessed by parentheses) is a 1x1 cell array that can contain any class of array of any size; to access the contents of an element of a cell array, you use curly brackets: age(2) is the second element of the cell array, age{2} are the contents of said element, i.e. your 1x2 array of numbers.