Blog MLab
Matlab syntax tricks

By Raphaël - December 18th, 2016

Matlab

0 Comment

Arrays
Flow control: for and switch

Structures

Structures are arrays!

Structures are the Matlab version of the hash table. But many programmers forget that they are not just an associative table, they are an array of associative tables.

Here is a schematic comparison between arrays and structures:

In practice, one can then define many elements in a structure array:

>> S = struct('Hello', 'world!', 'answer', 42); % Defines the fields of the structure for the first element
>> size(S)

ans =

     1     1

>> S(2,3).Hello = 'Dolly';    % Index the structure S as a regular array
>> size(S)

ans =

     2     3

Note that in this exemple all the non-assigned elements contain empty fields:

>> S(2,2)           % Also holds with elements (1,2), (1,3) and (2,1)

ans = 

  struct with fields:

     Hello: []
    answer: []

Defining fields of an empty structure

To define an empty structure, many people do the following:

>> S = struct('a', [], 'b', [])

S = 

  struct with fields:

    a: []
    b: []

this syntax is correct (it doesn't generate an error) but does not exactly create an empty strucure: it defines a structure with fields containing empty arrays. The best evidence that the structure S is not empty is provided by a size check:

>> size(S)

ans =

     1     1

To create a truly empty structure, one has to use empty cells {} for all the field definitions:

>> S = struct('a', {}, 'b', {})

S = 

  0×0 empty struct array with fields:

    a
    b

>> size(S)

ans =

     0     0

And in the case you don't want an empty structure but want to assign empty cells to all the fields? Then the kind-of-awkward following syntax has to be employed:

>> S = struct('a', {{}}, 'b', {{}})

S = 

  struct with fields:

    a: {}
    b: {}

Calling structure fields dynamically

Let's continue playing with structures. The syntax to dynamically call the field fieldname from the structure S is the following:

S.(fieldname)

If you're asking yourself how this could be useful, imagine that you have the following structure:

S = 

  struct with fields:

    small: 2
    large: 1024
     huge: 100000

and that you want to select one of the fields at random. Then all you have to do is:

>> F = fieldnames(S);      % F contains the field names {'small', 'large', 'huge'}
>> i = randi(numel(F));    % Select an index at random, here i=3
>> S.(F{i})

ans =

      100000

Extracting all the values of a given field

Have a structure containing many elements with different fields, one may want to isolate all the values of a given field in an array. Of course one can use a loop for this, but the following syntax is more elegant:

A = [S(:).field];

The principle is simple: take all elements columnwise with (:), select a given field with .field and wrap the result in an array with the braces [...].

A classical exemple is when you want to filter out objects of a black and white image after a segmentation with regionprops.

On the speed side, this syntax is much more efficient than a foor loop. Consider for instance the following exemple:

% Define a structure with fields x and y containing each a vector of 100 random values
S = struct('x', mat2cell(rand(100,1), ones(100,1), 1), 'y', mat2cell(rand(100,1), ones(100,1), 1));

% Extracting the 'x' vector with a loop
tic
A = NaN(numel(S),1);
for i = 1:numel(S)
  A(i) = S(i).x;
end
toc                     % Elapsed time is 0.033700 seconds.

% Using the smart syntax
tic; 
A = [S(:).x]; 
toc                     % Elapsed time is 0.000272 seconds. 120 times faster !
Arrays
Flow control: for and switch

Comments

There are no comments on this post so far. Write a comment.