Indexing and slicing
Indexing in MATLAB is unusually expressive and is the substance of much idiomatic code. Three indexing modes — parenthesis, brace, and dot — apply to different container classes; within parenthesis indexing the language admits linear, subscript, colon, range, end, and logical forms, each with distinct semantics. Indexing on the left-hand side of an assignment is also assignment-into-place: a slice can be read, modified, or deleted by indexing.
One-based, column-major
The first element of an array is A(1). The N-th element is A(N). The last element is A(end). Linear indexing — supplying a single index to a multi-dimensional array — visits elements in column-major order:
A = [1 2 3; 4 5 6];
A(1) % 1
A(2) % 4 (next element down the column)
A(3) % 2 (top of second column)
A(end) % 6
The one-based convention is consistent with mathematical notation but is the source of conversion bugs in code translated from C or Python; the end keyword removes the most common arithmetic involving array lengths.
Subscript indexing
Multiple comma-separated indices select along each dimension:
A = magic(5);
A(3, 4) % scalar, element at row 3, col 4
A(2, :) % the entire second row (1×5)
A(:, 2) % the entire second column (5×1)
A(2:4, [1 3 5]) % 3×3 subblock
A single colon : matches the whole dimension. A vector of indices selects multiple positions; the result has the dimensions of the index expression along that axis. Indices may repeat: A([1 1 1], :) produces a 3×5 matrix consisting of three copies of the first row.
The keyword end inside an index expression is the index of the last element along the dimension being indexed:
A(end, end) % bottom-right element
A(end-2:end, :) % last three rows
A(1:end/2, :) % first half of the rows
end may participate in arithmetic; the parser evaluates the index expression and substitutes end with the appropriate size.
Linear indexing
A single index applied to a multi-dimensional array is interpreted in column-major order:
A = [1 2 3; 4 5 6]; % 2×3
A(1) % 1
A(4) % 5
A([1 3 5]) % [1 2 3] (first row read in column-major order)
A(end) % 6
The conversion between linear indices and subscripts uses sub2ind and ind2sub:
sub2ind(size(A), 2, 3) % 6
ind2sub(size(A), 5) % returns row=1, col=3
Linear indexing is the fastest indexing form and is the basis of much vectorised code.
Logical indexing
A logical array used as an index selects the elements where the index is true. The shape of the result depends on the shape of the source and the index:
x = 1:10;
mask = mod(x, 2) == 0
% 1×10 logical: [0 1 0 1 0 1 0 1 0 1]
x(mask)
% [2 4 6 8 10]
Logical indexing is the idiomatic MATLAB filter. The standard find function returns the linear indices where a logical array is true and is occasionally a clearer alternative:
find(x > 5) % [6 7 8 9 10] (the positions)
x(find(x > 5)) % [6 7 8 9 10] (the values; same as x(x > 5))
The two are equivalent for selection; logical indexing is preferred for clarity, find is preferred when the positions themselves are wanted.
Indexed assignment
The left-hand side of an assignment may be an indexed expression. The right-hand side must have a shape that matches the indexed region:
A = zeros(3, 3);
A(1, :) = [10 20 30]; % set the first row
A(:, 2) = 99; % set the second column to 99 (scalar broadcasts)
A(A < 50) = 0; % zero everything below 50
The third line is the canonical masked assignment: a logical index on the LHS sets only the selected positions.
A right-hand side of [] deletes the indexed region. The deletion must remove a whole row, column, or slab — partial deletion that would leave a non-rectangular array is an error.
A(:, 2) = [] % delete the second column; A is now 3×2
v = 1:10;
v(3:5) = [] % delete elements 3..5; v becomes [1 2 6 7 8 9 10]
Growth-by-assignment
Assigning past the end of an array grows the array, filling new positions with zeros (or empty strings, for string arrays):
v = [1 2 3];
v(5) = 99
% v = [1 2 3 0 99]
Growth-by-assignment is convenient but slow if performed in a loop; preallocation is preferred (see Matrices and N-d arrays).
Brace indexing into cell arrays
The {} form retrieves the contents of cells; the () form retrieves a smaller cell array:
c = {1, "two", [3 4 5]};
c{2} % "two" (the contents, a string scalar)
c(2) % {"two"} (a 1×1 cell containing the string)
[c{1:2}] % a comma-separated list; here flattened to [1 "two"]
A comma-separated list expansion is one of MATLAB’s distinctive corners: c{:} produces as many separate values as the cell has elements and is the canonical way to pass a cell of arguments as a variable-length argument list:
args = {0, 2*pi, 100};
linspace(args{:}) % equivalent to linspace(0, 2*pi, 100)
Dot indexing into structs
Field access on a struct uses the dot:
s = struct('name', "Ada", 'birthYear', 1815);
s.name % "Ada"
s.birthYear % 1815
A struct array of length N supports s.name returning a comma-separated list (the principal idiom for “extract the same field from every element”):
arr = struct('x', {1, 2, 3});
[arr.x] % [1 2 3]
The dynamic-field form s.(name) permits programmatic access:
fname = "birthYear";
s.(fname) % 1815
Multi-dimensional struct array indexing
A struct array supports the full indexing grammar — (), (:), end — and dot access. Combining indexed slicing with dot field selection on the result is the source of the most-elaborate indexing expressions in MATLAB:
arr(2:end).x % comma-separated list of x fields for elements 2..end
{arr(2:end).x} % the same, gathered into a cell array
[arr(arr.flag).x] % cannot work this way directly; see arrayfun
The mechanism is rich, occasionally confusing, and best learned by example. The official documentation page on advanced indexing — mathworks.com/help/matlab/math/array-indexing.html — is the reference for the corner cases.
The end keyword in detail
end inside an index expression has access to the size of the dimension being indexed. In a 1-d context it is the length; in a multi-d context it depends on the dimension number in the slot. The function size(A, k) is what end reduces to:
A = magic(5);
A(end, 1) % 5,1
A(1, end) % 1,5
A(end-1, end-1) % 4,4
A(end:-1:1, :) % rows reversed
end may not appear outside of an indexing expression except in the keyword form that terminates if, for, etc.
Indexing into function output
A function’s return value can be indexed directly only when assigned to a temporary — there is no direct f(x)(1) form. The remedy is either an intermediate variable or the subsref/getfield function:
% Common pitfall:
% size(A)(1) % syntax error in MATLAB
% Remedies:
sz = size(A); sz(1)
size(A, 1) % most uses are served by an explicit argument
This restriction is the language’s single most-cited vs Octave incompatibility: GNU Octave permits the chained form size(A)(1) and many programs that work in Octave fail to parse in MATLAB.