Loren on the Art of MATLAB

Turn ideas into MATLAB

Structures and Comma-Separated Lists 51

Posted by Loren Shure,

I have seen an increasing number of questions on structures and extracting information from them in a vectorized way. Though I've already covered portions of this topic in earlier posts, I'll try to bring together a coherent view here.

Contents

Simple Structure Array

Let's work with a simple structure array. By simple here, I mean one that does not have nested structures inside (though I don't believe there's any such defined term in MATLAB). We can use the function struct to create one or we can use direct notation. The following constructs are for s1 and s2 are equivalent.

clear
s1 = struct('name','Loren','FavoriteNumber',17)
s2.name = 'Loren';
s2.FavoriteNumber = 17
s1 = 
              name: 'Loren'
    FavoriteNumber: 17
s2 = 
              name: 'Loren'
    FavoriteNumber: 17

Are they the same?

isequal(s1,s2)
ans =
     1

Now let's add more people to the "database," along with their favorite numbers. See this reference for illumination on the structure inputs.

s1(end+1).name = 'Douglas';
s1(end).FavoriteNumber = 42;
s2(end+1) = struct('name','Douglas','FavoriteNumber',42);
isequal(s1,s2)
ans =
     1

What happens when we look at one of these, say s1?

s1
s1 = 
1x2 struct array with fields:
    name
    FavoriteNumber

We see that it's a struct with size 1x2, and fields named name and FavoriteNumber. We can also see the first element, s1(1) and the associated values, since they are not too large to display.

s1(1)
ans = 
              name: 'Loren'
    FavoriteNumber: 17

Let's try digging a little deeper now and see if we can group the data differently and collect it into some other MATLAB arrays. Start with the names.

s1.name
ans =
Loren
ans =
Douglas

When I display s1.name, I see ans = displayed twice, once for each element in the struct array. It's as if I executed this code:

s1(1).name,s1(2).name
ans =
Loren
ans =
Douglas

See how I wrote that last expression? It was really 2 expressions in this case, separated by one of the usual MATLAB statement separators, the comma, hence the term you see in the documentation "comma-separated list."

Converting Numeric Structure Fields to a Variable

Now I want to take the output from a specific field in the structure array and place the values together in one MATLAB variable. I can do this with

  • a for loop,
  • using the function deal,
  • by taking advantage of notation new in Release 14.

I'll show all 3; my preference is for the newest notation, in part because of its compactness and clarity of intent, but it should also be a bit faster in general.

ls1 = length(s1);

% for
numFor = zeros(1,ls1);
for ind=1:ls1
    numFor(ind) = s1(ind).FavoriteNumber;
end

% deal
[numDeal(1), numDeal(2)] = deal(s1.FavoriteNumber);

% R14 notation, Loren's preferred method!
numFavorite = [s1.FavoriteNumber];

Check for correct answers.

isequal(numFor, numDeal, numFavorite)
ans =
     1

The solution using deal requires you know how many outputs you want, which can be awkward to write in an automated way. I can place the results into a cell array and then convert that to a numeric array. Here, I create a comma-separated list of output values, and then place them inside [] to build the output cell array in numDealC. Then I convert this cell array to a numeric one using cell2mat.

[numDealC{1:ls1}] = deal(s1.FavoriteNumber);
numDeal2 = cell2mat(numDealC);
isequal(numFavorite, numDeal2)
ans =
     1

Converting String Structure Fields to a Cell Array

Now let's work on the names. Since they are different lengths, the names probably belong in a cell array of strings. Using the same idea of having a comma-separated list for the output values, I place each output into a cell. The right-hand side is also a comma-separated list, and, with Release 14 (MATLAB 7), I can parcel out these values to multiple output values without using deal or some other means of distribution. Remember, each cell in a cell array is itself a MATLAB array.

[names{1:ls1}] = s1.name
names = 
    'Loren'    'Douglas'

I could have easily done this instead (thanks to John's comment for the reminder).

names = {s1.name}
names = 
    'Loren'    'Douglas'

I now have a cell array of string names and each name corresponds to the associated value in the numFavorite array. I encourage you to check out the references here, and to post any follow-up thoughts.

References

Blog Articles


Published with MATLAB® 7.2

18 views (last 30 days)  | |

Comments

To leave a comment, please click here to sign in to your MathWorks Account or create a new one.