Polyglot
Languages MATLAB cell arrays
MATLAB § cell-arrays

Cell arrays

A cell array is a MATLAB container whose elements may be arrays of any class and any shape. Where a numeric matrix demands homogeneity — every entry is, say, a double — a cell array imposes nothing. The mechanism is the canonical way to store a list of strings of unequal length, a heterogeneous record, or a variable-length argument list. The class is cell; the constructor is curly braces { }; indexing uses both () (subset of the cell array) and {} (contents of cells).

Constructing cell arrays

c = {1, "two", [3 4 5], magic(3)};
size(c)                  % [1 4]
class(c)                 % 'cell'

Each cell contains an independent array. The shape of the cell array itself (here 1×4) is independent of the shape of the contents. A 2-d cell array uses semicolons or newlines:

C = {1, "row"; [1 2 3], magic(2)}
% 2×2 cell:
%   [1]                ["row"]
%   [1 2 3]            [2×2 double]

An empty cell of size M×N is built by cell(m, n). The function cell(0, 0) returns the canonical empty cell {}.

The two indexing forms

The most important fact about cell arrays is the distinction between () and {}:

FormYieldsResult class
c(i)A 1×1 cell containing the i-th cellcell
c{i}The contents of the i-th cellThe class of the contents
c = {1, "two", [3 4 5]};
c(2)                        % {"two"}        (a 1×1 cell)
c{2}                        % "two"          (the string)
class(c(2))                 % 'cell'
class(c{2})                 % 'string'

The () form is appropriate when re-shaping a cell array — selecting a subset, reordering, transposing. The {} form is appropriate when extracting the contents for use in a computation. The reader of MATLAB learns the distinction by example; the most-cited mistake is using c(2) + 1 and being puzzled by the resulting error.

Comma-separated lists

The brace expansion c{:} produces a comma-separated list — not a single value, but a sequence of values that the caller may consume. Three principal uses:

As a variable-length argument list. A function called with f(c{:}) receives the contents of the cells as separate arguments:

args = {0, 2*pi, 100};
linspace(args{:})           % equivalent to linspace(0, 2*pi, 100)

Concatenated into an array. [c{:}] concatenates the contents horizontally; [c{:}].' then turns them into a column:

c = {1, 2, 3};
[c{:}]                      % [1 2 3]

As multiple return values. [a, b, c] = deal(c{:}) distributes the cells into separate variables; deal is the canonical helper.

varargin and varargout

A function declared with the special parameter varargin receives any extra trailing arguments as a cell array. Symmetrically, varargout is a cell of output values:

function info = describe(varargin)
    info = sprintf("%d arguments\n", nargin);
    for k = 1:nargin
        info = info + sprintf("  arg %d: %s\n", k, class(varargin{k}));
    end
end

describe(1, "two", [3 4 5])
% "3 arguments
%    arg 1: double
%    arg 2: string
%    arg 3: double"

The mechanism is the basis of essentially every variadic function in the standard library.

Iterating cells

A for loop over a cell array binds the loop variable to the contents of each cell in turn — except that the assignment is to a 1×1 cell rather than the inner contents. The idiom is:

c = {"alpha", "beta", "gamma"};
for k = 1:numel(c)
    disp(c{k})              % brace to extract
end

The higher-order function cellfun applies a function to each cell and returns either a numeric array (the default) or, with the 'UniformOutput', false option, a cell array of results:

lengths = cellfun(@strlength, ["alpha", "beta", "gamma"])
% [5 4 5]

upper_cells = cellfun(@upper, c, 'UniformOutput', false)
% {"ALPHA", "BETA", "GAMMA"}

The 'UniformOutput' distinction is one of MATLAB’s more idiomatic conveniences: it lets the same function return scalar-per-cell or a cell of varied-shape outputs.

Cells in practice

The conventional uses of cell arrays are limited but important:

  • A list of strings of differing length. Before R2016b this was the only way to store such a list; today a string array is usually preferred. Cells remain common in legacy code and in interfaces that have not migrated.
  • An argument list. A cell {a, b, c} passed as f(args{:}) is the canonical variadic-argument idiom.
  • A heterogeneous record. A cell with a fixed convention for each slot — {name, age, address} — was once a common record type; today struct and table are preferred.
  • The output of certain library functions. regexp(..., 'tokens') returns a cell of cells; strsplit returns a cell of strings; fieldnames(s) returns a cell of field names.

Cell vs string array

A string array (introduced R2016b) is in many cases a drop-in replacement for a cell of char arrays. The two are not the same: a string array has a shape (rows and columns), each element is a single string, and == is string equality. A cell of strings has cells (each containing an independent array) and is less efficient for the common case of “a list of strings”.

sa = ["alpha", "beta", "gamma"]      % string array
ca = {'alpha', 'beta', 'gamma'}      % cell of char arrays

sa(2)                                  % "beta"
ca{2}                                  % 'beta'
sa == "beta"                           % [false true false]
strcmp(ca, 'beta')                     % [0 1 0]

The general recommendation in new code is to prefer string arrays for text; cell arrays remain the right choice when the contents are heterogeneous.

Memory and copies

A cell array is itself an array of pointers; the contents of each cell are stored separately. Assigning a cell array to a new variable shares the outer structure under copy-on-write; modifying a cell triggers a copy of the affected cell. The mechanism is efficient for cells of large arrays.

c = {large_matrix};
d = c;                  % shares
d{1}(1, 1) = 0;         % copies only the first cell's contents