2

To vectorize a matrix in MATLAB, you can execute this simple command:

A = reshape(1:9, 3, 3)
% A =
% [1 4 7]
% [2 5 8]
% [3 6 9]

b = A(:)
% b = [1 2 3 4 5 6 7 8 9]'

But how about if you have a matrix that you want to first slice, then vectorize? How do you go about doing this without assigning to a temporary variable?

Let's say A is now:

A = reshape(1:27, 3, 3, 3)
% A(:,:,1) =
% [1 4 7]
% [2 5 8]
% [3 6 9]    

% A(:,:,2) =
% [10 13 16]
% [11 14 17]
% [12 15 18] 

% A(:,:,3) =
% [19 22 25]
% [20 23 26]
% [21 24 27] 

If you run

b = A(:,:,1)(:)
% Error: ()-indexing must appear last in an index expression.

Is there some function, vectorize(A) that gives this functionality?

b = vectorize(A(:,:,1))
% b = [1 2 3 4 5 6 7 8 9]'

Or if not a function, is there an alternative method than

tmp = A(:,:,1)
b = tmp(:)

Thanks in advance for the guidance!

marcman
  • 3,233
  • 4
  • 36
  • 71
  • 3
    After posting, I realize `b = reshape(A(:,:,1), 1, size(A,1) * size(A,2))` also does the trick. Is this the most elegant solution? – marcman Nov 10 '15 at 21:13
  • 3
    I think your question is just a variation of this: http://stackoverflow.com/questions/3627107/how-can-i-index-a-matlab-array-returned-by-a-function-without-first-assigning-it This issue keeps coming up in MATLAB, and the short answer is to use a temporary variable. – Matthew Gunn Nov 10 '15 at 21:15

3 Answers3

4

If only elegance could be measured, but here's one to get through the night -

A(1:numel(A(:,:,1))).'
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • Quite clever! But in terms of readable code, the clunky: `tmp = A(:,:,1); b = tmp(:)` I'd argue is superior. I've never quite understood the aversion of some programmers to an extra '\n' character in their code. – Matthew Gunn Nov 10 '15 at 21:20
  • 1
    @MatthewGunn Some mad people are one-liner lovers, it's hard to understand `em ;) – Divakar Nov 10 '15 at 21:23
  • 1
    I'm a reformed one-liner lover :P Too many instances of looking at old code and trying to figure out WTF I was doing. – Matthew Gunn Nov 10 '15 at 21:25
  • 1
    It's less about compaction in scripting, and more about nesting operations on the command line. Sometimes it is just easier, particularly when testing code snippets at a breakpoint when there are already tons of variables in your workspace. – marcman Nov 10 '15 at 21:25
  • But this doesn't work for slices other than the first. It could be easily solved, though – Luis Mendo Nov 10 '15 at 22:08
  • @LuisMendo Yeah, need to offset for each dim-3 index. Might add that later on for completeness, thanks for pointing that out :) – Divakar Nov 10 '15 at 22:12
  • This one-liner only works to vectorize A(:,:,1), but won't for A(:,:,2) etc. – Felix Darvas Nov 11 '15 at 00:13
2

This is a function that I've seen many seasoned Matlab users add to their code hoard by hand:

function A = vectorize(A)
A = A(:);
% save this code as vectorize.m

Once you've got vectorize.m on your path, then you can do what you want in one line.

You can define the function inline if you prefer:

vectorize = inline( 'A(:)' );

but then of course you have to ensure that that's in memory for every session.

If for some reason it's unacceptable to write and save your own functions to disk (if so, I wonder how your sanity ever survives using Matlab, but it takes all sorts...) then the following code snippet is a one-liner that uses only builtins, works for arbitrarily high-dimensional A, and is still not too unreadable:

reshape( A, numel(A), 1 )

Note that this, in common with (:) but contrary to what you assume in your question, produces a column vector. Its disadvantage is that A must already be assigned in the workspace, and that assignment may require one extra line. By contrast, the function version can work even on unnamed outputs of other operations—e.g.:

A = vectorize( randn(5) + magic(5) )
jez
  • 14,867
  • 5
  • 37
  • 64
  • This allows a one liner solution that passes the code readability test. – Matthew Gunn Nov 10 '15 at 21:29
  • Good solution also. True about the column vector, but it was more convenient to write it on a line. I've added the apostrophes to show transpose. – marcman Nov 10 '15 at 21:31
  • Just a note: apparently [`vectorize()`](http://www.mathworks.com/help/matlab/ref/vectorize.html) is an existing MATLAB function completely unrelated to this task. Just in case someone is thinking of implementing their own, perhaps rethink the name. Maybe `mat2vec(A)`? – marcman Nov 10 '15 at 21:38
  • Yeah, my own version of this is actually called `vec`. But mostly I just ignore this problem and try not to worry about overshadowing things I've never heard of. In general you can't avoid it: Matlab has no namespace protection and keeps moving the goalposts. After 20 years of using the thing, my visceral response to any Matlab question starts with "In general, don't use Matlab. But if you are more than, say, 50% certain that you will die if you *don't* use Matlab, then..." That percentage keeps climbing. – jez Nov 10 '15 at 21:43
  • 1
    @jez Maybe one day I'll hop the fence to Python. I hear they have free beer over there. – marcman Nov 10 '15 at 21:51
0

One-liner for arbitrary indices.

i=3; 
A((i-1)*numel(A(:,:,i))+(1:numel(A(:,:,i)))).'
Felix Darvas
  • 507
  • 3
  • 5