MATLAB & GNU Octave Module 2 – Vectors, matrices and numeric types
Reshape, sort, find and set operations on arrays
Reshape, flip and shift Octave and MATLAB arrays, sort with index outputs and sortrows, and use find, ismember, unique and set operations safely.
What you will learn
- Use reshape, flip, circshift and permute without changing the order of the data by accident
- Sort with the index output, sort records by several keys and keep ties in input order
- Find elements, unique values and set relations between arrays
- Count the occurrences of each distinct value with unique and accumarray
Before you start
What you’ll learn · Before you start
What you will learn
- Use reshape, flip, circshift and permute without changing the order of the data by accident
- Sort with the index output, sort records by several keys and keep ties in input order
- Find elements, unique values and set relations between arrays
- Count the occurrences of each distinct value with unique and accumarray
Before you start
On this page
Eight students with three marks each: putting them in merit order takes one sortrows call, yet the wrong call
leaves tied students in whatever order the file had, puts absent students at the top or splits each record apart.
Rearranging arrays is everyday work in MATLAB and Octave, and every function involved makes a precise promise about
order.
Here you reshape, flip, shift and permute arrays without scrambling them, sort with the index output and several
keys, find values with find and ismember, and count distinct values with unique and accumarray.
reshape changes the shape and keeps the order
reshape(A, m, n) returns the same elements in an m-by-n shape. It never moves an element out of its place in
column-major order: Storing and counting the elements of an array column by column: the whole first column, then the second. MATLAB, Octave and Fortran use it; C stores rows first, which is row-major order. More in “Indexing: subscripts, colon, end and linear indices”: it takes the elements as A(:) lists them and fills the new
shape down its columns. The number of elements must match, and one size may be [] for “whatever fits”:
from session import prompt, version
version()
prompt("reshape_demo.m", errors=1) Output
# GNU Octave (aarch64-apple-darwin25.4.0) version 11.3.0 $ octave-cli --quiet octave:1> reshape(1:6, 2, 3) ans = 1 3 5 2 4 6 octave:2> reshape(1:6, 3, 2) ans = 1 4 2 5 3 6 octave:3> x = 1:8; octave:4> reshape(x, [], 2) ans = 1 5 2 6 3 7 4 8 octave:5> reshape(1:6, 4, 2) error: reshape: can't reshape 1x6 array to 4x2 array octave:6> A = [1 2 3; 4 5 6]; octave:7> reshape(A, 3, 2) ans = 1 5 4 3 2 6 octave:8> A' ans = 1 4 2 5 3 6
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 reshape_session.py
reshape(1:6, 2, 3) puts 1 and 2 in column 1, and reshape(x, [], 2) worked out 4 rows for 8 elements. Six elements
cannot make a 4-by-2 matrix, hence can't reshape 1x6 array to 4x2 array. The last two lines hold the trap: a matrix
reshaped to the transposed shape is not its transpose. Step through reshape(A, 3, 2) to see why:
The drawing shows the whole scene; its 5 steps are listed below.
Every step as text
- An empty 3-by-2 shape. A = [1 2 3; 4 5 6] has six elements. In column-major order they are 1, 4, 2, 5, 3 and 6: column 1 of A first, then column 2, then column 3.
- Element 1 goes first. reshape takes the elements in that order and fills the new shape the same way, down its first column. A(1), the 1, goes to the top.
- Down the first column. A(2) is 4, the second row of A's first column, and A(3) is 2, the top of its second column. They fill the rest of new column 1.
- Then the second column. A(4), A(5) and A(6), which are 5, 3 and 6, fill new column 2 from the top. No element moved out of its place in the sequence.
- Not the transpose. The result is [1 5; 4 3; 2 6], as the session printed. A' has the same 3-by-2 shape but reads [1 4; 2 5; 3 6], because the transpose moves elements and reshape never does.
A(:) of A = [1 2 3; 4 5 6] is 1, 4, 2, 5, 3, 6, and that sequence fills the 3-by-2 shape column by column, giving
[1 5; 4 3; 2 6]. Use reshape when the order in memory is already the order you want, as with a week of hourly
readings in one vector, which reshape(x, 24, []) turns into one day per column; use the transpose ' when rows
must become columns.
reshape to turn rows into columns
reshape(A, size(A, 2), size(A, 1)) has the transposed shape and scrambled contents whenever A has more than one
row and more than one column. For rows that should become columns, write A'.
Checkpoint
Check: reshape and column-major order
flip, circshift and permute move elements on purpose
Unlike reshape, these functions move elements, each in one documented way:
from session import prompt, version
version()
prompt("moves_demo.m", errors=1) Output
# GNU Octave (aarch64-apple-darwin25.4.0) version 11.3.0 $ octave-cli --quiet octave:1> x = [1 2 3 4]; octave:2> fliplr(x) ans = 4 3 2 1 octave:3> circshift(x, 1) ans = 4 1 2 3 octave:4> circshift(x, -1) ans = 2 3 4 1 octave:5> A = [1 2 3; 4 5 6]; octave:6> flipud(A) ans = 4 5 6 1 2 3 octave:7> circshift(A, 1, 2) ans = 3 1 2 6 4 5 octave:8> B = reshape(1:24, 2, 3, 4); octave:9> size(permute(B, [3 1 2])) ans = 4 2 3 octave:10> shift(x, 1) error: 'shift' undefined near line 1, column 1
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 moves_session.py
| Function | What it does | In the session |
|---|---|---|
fliplr(A), flipud(A), flip(A, dim) |
reverse the columns, the rows, or any dimension | fliplr([1 2 3 4]) is 4 3 2 1 |
circshift(A, n) |
moves elements n places along the first dimension that is not 1, wrapping round; negative n moves the other way | circshift(x, 1) is 4 1 2 3 |
circshift(A, n, dim) |
the same along a chosen dimension | circshift(A, 1, 2) moves each row’s elements one column right |
permute(A, order) |
reorders the dimensions themselves | a 2x3x4 array becomes 4x2x3 with [3 1 2] |
circshift wraps round, so nothing is lost: the 4 that fell off the end of [1 2 3 4] came back at the front. That
suits periodic data, such as a daily cycle of 24 hourly values that should start at 06:00 rather than at midnight:
circshift(x, -6) moves every value six places towards the front, and the first six wrap round to the end.
permute is the transpose for arrays of any number of dimensions: permute(B, [3 1 2]) makes the pages the first
dimension, so a 2x3x4 array becomes 4x2x3.
shift was removed in Octave 10
Octave 8 deprecated shift, and Octave 10 removed it in favour of circshift, as the release notes of Octave 10
list. Older scripts that call shift(x, 1) now stop with 'shift' undefined, as the last line of the session
shows; replace the call with circshift(x, 1).
Checkpoint
Check: flip, circshift and permute
sort returns the order as well as the values
[s, k] = sort(x) returns the sorted values and, in k, the position each one came from, so that x(k) is s. Ties
keep their input order, which makes sort a stable sort: A sort that keeps equal values in the order they had in the input. sort and sortrows in MATLAB and Octave are stable, so ties keep their input order unless another key breaks them.: the Octave manual says equal
elements are listed in the order in which they appeared, and MathWorks says MATLAB’s sort is stable. Step through
the four values of the session’s first line:
The drawing shows the whole scene; its 5 steps are listed below.
Every step as text
- Four values, two of them equal. x = [3 1 2 1]. The two 1s are equal, so only their positions, 2 and 4, tell them apart.
- The smallest value first. In ascending order the 1s come first. A stable sort keeps equal values in their input order, so the 1 from position 2 takes s(1), and k(1) records the 2.
- The other 1 next. The 1 from position 4 comes second, never before the one from position 2, so k(2) is 4.
- Then 2 and 3. The 2 from position 3 and the 3 from position 1 follow, so k(3) is 3 and k(4) is 1.
- k replays the sort. s = [1 1 2 3] and k = [2 4 3 1], as the session printed, and x(k) gives s again. Indexing any other array of the same length with k puts it in the same order.
from session import prompt, version
version()
prompt("sort_demo.m") Output
# GNU Octave (aarch64-apple-darwin25.4.0) version 11.3.0
$ octave-cli --quiet
octave:1> [s, k] = sort([3 1 2 1])
s =
1 1 2 3
k =
2 4 3 1
octave:2> sort([3 NaN 1 2])
ans =
1 2 3 NaN
octave:3> sort([3 NaN 1 2], 'descend')
ans =
NaN 3 2 1
octave:4> M = [3 10; 1 20; 2 30];
octave:5> sort(M)
ans =
1 10
2 20
3 30
octave:6> [~, k] = sort(M(:, 1));
octave:7> M(k, :)
ans =
1 20
2 30
3 10
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 sort_session.py
k = [2 4 3 1] is a permutation vector: A vector holding each of the positions 1 to n exactly once, in some order, such as the second output k of [s, k] = sort(x). Indexing an array with it reorders the array the same way., and it is the useful part: indexing
any other array of the same length with k puts it in the same order. The last two lines use it to keep rows
together. sort(M) sorted each column of M on its own and split the rows apart: 3 sat next to 10 and now sits next
to 30. Sorting the first column, then indexing every row with its k, kept each pair whole.
NaN values sort last in ascending order and first in descending order, in both programs (the Octave manual treats
NaN as greater than any other value; MathWorks documents the same placement). A ranking sorted with 'descend'
therefore puts a missing total at the very top.
Key idea
The second output of sort is the order itself: index the other arrays with it to keep records together, and
remember that ties keep their input order and NaN goes first in descending order.
Checkpoint
Check: sort with its index output
sortrows sorts records by several keys
sortrows(M, cols) reorders whole rows. Each entry of cols is a column to sort by, the first deciding first, and
a negative entry sorts that column in descending order. This program ranks eight students by total marks, highest
first, with ties broken by roll number:
% rank_students.m: eight students ranked by total marks, ties broken by roll number
% roll maths physics chemistry
marks = [105 88 90 81
101 78 65 70
108 92 88 79
102 85 72 56
103 92 88 79
106 59 61 70
104 67 74 72
107 73 80 77];
total = marks(:, 2) + marks(:, 3) + marks(:, 4);
[~, k] = sort(total, 'descend'); % the order of the totals alone
printf('sort by total: rolls %s\n', mat2str(marks(k, 1)'));
ranked = sortrows([marks(:, 1) total], [-2 1]); % total down, then roll up
printf('sortrows [-2 1]: rolls %s\n', mat2str(ranked(:, 1)'));
printf('%4s %6s\n', 'roll', 'total');
printf('%4d %6d\n', ranked'); from session import run, version
version()
run("""
octave-cli --no-init-all rank_students.m
octave-cli --no-init-all station_counts.m
""") Output
# GNU Octave (aarch64-apple-darwin25.4.0) version 11.3.0
$ octave-cli --no-init-all rank_students.m
sort by total: rolls [105 108 103 107 101 102 104 106]
sortrows [-2 1]: rolls [103 105 108 107 101 102 104 106]
roll total
103 259
105 259
108 259
107 230
101 213
102 213
104 213
106 190
$ octave-cli --no-init-all station_counts.m
station count
117 5
204 3
351 2
488 2
12 readings in all, 12 counted
in the order first seen: [351 117 488 204]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 tables_session.py
Three students have 259 and three have 213. Sorting the totals alone kept the ties in file order, 105, 108 and 103,
because sort is stable. sortrows([marks(:, 1) total], [-2 1]) states the rule instead: column 2, the total,
descending, then column 1, the roll number, ascending, which gives 103, 105, 108. Stability is a property of the
algorithm; a second key is a decision you write down, and only the second survives a change in the input file.
[~, order] = sortrows(…) also returns the row order, to apply to other arrays as k was applied above. The second
half of the session belongs to the last section of this lesson.
Relying on file order to break ties
A merit list that leans on stability is right only while the file happens to be in roll order. Name every key the
rule has, [-2 1] here, and the result no longer depends on how the data arrived.
Checkpoint
Check: sortrows with several keys
find and ismember say where values are
find returns the positions where a condition holds, and ismember says whether each value of one array occurs in
another and where:
from session import prompt, version
version()
prompt("find_demo.m") Output
# GNU Octave (aarch64-apple-darwin25.4.0) version 11.3.0 $ octave-cli --quiet octave:1> y = [5 1 4 2 7]; octave:2> find(y > 2) ans = 1 3 5 octave:3> find(y > 2, 2) ans = 1 3 octave:4> A = [0 3; 4 0; 0 5]; octave:5> [r, c] = find(A) r = 2 1 3 c = 1 2 2 octave:6> [tf, loc] = ismember([4 9 1], y) tf = 1 0 1 loc = 3 0 2 octave:7> codes = [351 117 117 488 204 117 351 204 117 488 117 204]; octave:8> [tf, loc] = ismember([117 300 488], codes) tf = 1 0 1 loc = 11 0 10 octave:9> find(codes == 117, 1) ans = 2
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 find_session.py
| Question | Call | In the session |
|---|---|---|
| Where is the condition true? | find(y > 2) |
positions 1, 3 and 5 |
| Where are the first n? | find(y > 2, n) |
find(y > 2, 2) is 1 and 3 |
| Which row and column? | [r, c] = find(A) |
the nonzeros of A, one row of r and c each |
| Is each value present, and where? | [tf, loc] = ismember(a, b) |
4 is at 3, 9 is absent, 1 is at 2 |
With one output on a matrix, find returns linear index: A single number that names an element by counting down the columns: in a matrix with m rows, row r of column c is element (c - 1) * m + r. sub2ind and ind2sub convert to and from subscripts. More in “Indexing: subscripts, colon, end and linear indices”, so [r, c] = find(A) is
the form to use when you need rows and columns. ismember answers in the shape of its first input: tf is 1 where
the value occurs and loc holds a position in the second array, 0 where it is absent.
Which position, when a value occurs more than once? The last lines of the session look up 117 and 488 in the
station log of the next section, where 117 occurs five times, first at position 2. Octave 11.3 answered 11 and 10,
the last occurrences, and its manual does not say which occurrence it returns. MathWorks documents the lowest index
for MATLAB, which would be 2 and 4. So code that needs the first occurrence asks for it in a way both programs
share: find(codes == 117, 1) gave 2.
ismember locations differ between the two programs
For repeated values, Octave 11.3 returned the last position and MATLAB documents the first. Use loc only to test
membership or with values you know are distinct, such as the output of unique, and use find(x == v, 1) when
the first position matters.
Checkpoint
Check: find and ismember
unique and set operations work on distinct values
unique(x) returns the distinct values, sorted. With three outputs, [u, i, j] = unique(x), it also returns the
positions i of the first occurrences, so that u is x(i), and the map j, so that x is u(j):
from session import prompt, version
version()
prompt("sets_demo.m") Output
# GNU Octave (aarch64-apple-darwin25.4.0) version 11.3.0 $ octave-cli --quiet octave:1> x = [3 1 2 1 3 3]; octave:2> [u, i, j] = unique(x) u = 1 2 3 i = 2 3 1 j = 3 1 2 1 3 3 octave:3> u(j) ans = 3 1 2 1 3 3 octave:4> unique(x, 'stable') ans = 3 1 2 octave:5> a = [5 1 4 2 7]; octave:6> b = [7 4 0]; octave:7> union(a, b) ans = 0 1 2 4 5 7 octave:8> intersect(a, b) ans = 4 7 octave:9> setdiff(a, b) ans = 1 2 5
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 sets_session.py
u(j) rebuilt 3 1 2 1 3 3 from three distinct values, and unique(x, 'stable') kept the order of first appearance,
3, 1, 2. Octave 11.3 returns i and j as columns and picks first occurrences, which MathWorks documents for MATLAB
too. The set operation: A function that treats arrays as sets of distinct values: union, intersect and setdiff, with ismember to test membership. In MATLAB and Octave their results are sorted unless 'stable' is given. union, intersect and setdiff treat their inputs as sets
of distinct values and return sorted results: setdiff(a, b) gave 1 2 5, in ascending order, not in the order of
a.
j is what makes counting easy. Each reading falls in the bin j of its code, and accumarray(j, 1) adds 1 per
reading to its bin. The second program of the session counts a log of 12 readings from four stations: 117 sent 5,
204 sent 3, 351 and 488 sent 2 each, and the counts add up to the 12 readings. 'stable' lists the stations in the
order first seen, 351 first.
% station_counts.m: how many readings each station sent, from a log of station codes
codes = [351 117 117 488 204 117 351 204 117 488 117 204];
[u, ~, j] = unique(codes); % u: the distinct codes, sorted; codes is u(j)
counts = accumarray(j, 1)'; % add 1 for every reading, in the bin of its code
printf('%7s %6s\n', 'station', 'count');
printf('%7d %6d\n', [u; counts]);
printf('%d readings in all, %d counted\n', numel(codes), sum(counts));
printf('in the order first seen: %s\n', mat2str(unique(codes, 'stable'))); Check a count against the total
Counts by accumarray must add up to the number of items: sum(counts) == numel(codes). One line catches a wrong
map, a lost bin or an input that was not what you thought.
Checkpoint
Check: unique, counts and set operations
Practise: rank, search and count
Do these in Octave with the arrays of this page, and check each against what Octave prints:
- Put one week of 168 hourly readings
x = 1:168into a 24-by-7 matrix, one day per column, and check thatD(1, 2)is 25, the first hour of day 2. - Add an absent student with roll 109 and a total of NaN to the ranking, and sort with
sortrows(R, [-2 1]). Where does 109 end up? Move it to the bottom withisnanand indexing. - With
codesfromstation_counts.m, list the stations that sent at least 3 readings, usingu,countsand indexing, and check that the list is 117 and 204. - Use
ismemberto test which of the codes 117, 300 and 488 appear in the log. Then find where 117 and 488 first appear in a way that gives 2 and 4 in both programs.
Finish with the practice questions, which pick your weakest idea first and explain each choice as you make it:
Practice that adapts to you
Practise this lesson
12 questions about 6 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.
Interview questions
Warm-up: what does the second output of sort give you, and why is it useful?
[s, k] = sort(x) returns the sorted values in s and, in k, the position in x that each sorted value came
from, so x(k) equals s. k is a permutation of 1:numel(x), and that makes it useful: indexing any other array
of the same length with k puts it in the same order, which is how you sort names, rows or a second measurement by
the values of the first without splitting records apart. Because sort is stable, equal values keep their input
order in k, as sort([3 1 2 1]) gives k = [2 4 3 1]. When the order of ties matters, sort by an explicit second
key with sortrows instead of relying on that.
Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.
-
Fresher to mid
You must publish a merit list of 2,000 students from a matrix of roll numbers and marks: highest total first, ties broken by roll number, absent students (NaN totals) at the bottom without a rank. How do you build it, and how do you show that the order is right?
-
Mid to senior
A log holds 2 million readings, each tagged with one of 350 station codes. Count the readings per station and list the 5 busiest, without a loop. What do you write, what does it cost, and how do you check the counts?
Key takeaways
reshapekeeps the column-major order and only changes the shape, so a reshape to the transposed shape is not a transpose;[]lets one size be worked out.fliplr,flipud,flip,circshiftandpermutemove elements in one documented way each, andshiftis gone since Octave 10.[s, k] = sort(x)returns the order ask; sorting is stable, NaN goes last ascending and first descending, andsorton a matrix sorts each column apart.sortrows(M, [-2 1])sorts whole rows by several keys, and an explicit second key, not the file order, should break ties.findreturns positions, linear unless you ask for rows and columns, andismemberreturns membership and locations.[u, i, j] = unique(x)gives the distinct values, their first positions and the map back, andaccumarray(j, 1)counts each value; set operations return sorted values.
Terms in this lesson
- permutation vector
- A vector holding each of the positions 1 to n exactly once, in some order, such as the second output k of [s, k] = sort(x). Indexing an array with it reorders the array the same way.
- set operation
- A function that treats arrays as sets of distinct values: union, intersect and setdiff, with ismember to test membership. In MATLAB and Octave their results are sorted unless 'stable' is given.
- stable sort
- A sort that keeps equal values in the order they had in the input. sort and sortrows in MATLAB and Octave are stable, so ties keep their input order unless another key breaks them.
References
- GNU Octave manual: Rearranging Matrices (reshape, sort, sortrows, circshift, permute) (The Octave Project Developers)
- GNU Octave manual: Finding Elements and Checking Conditions (find) (The Octave Project Developers)
- GNU Octave manual: Sets (unique) (The Octave Project Developers)
- GNU Octave manual: Set Operations (union, intersect, setdiff, ismember) (The Octave Project Developers)
- GNU Octave 10 release notes (shift removed, use circshift) (The Octave Project Developers)
- sort: sort array elements (MATLAB) (MathWorks)
- unique: unique values in array (MATLAB) (MathWorks)
- Resizing and Reshaping Matrices (MATLAB) (MathWorks)
Report a problem with this lesson
Kept only in this browser. Your Learn progress