If I have a short list (let's say two or three elements) I would like to have function that split it in several variables. Something like that:
li=[42 43];
[a b]=split(li)
--> a=42
--> b=43
I am looking for some way to make my code shorter in matlab. This one would be nice in some situations For instance:
positions=zeros(10,3);
positions= [....];
[x y z]=split(max(positions,1))
instead of doing:
pos=max(positions,1)
x=pos(1);
y=pos(2);
z=pos(3);
The only way I know of to do this is to use deal
. However this works with cell arrays only, or explicit arguments in to deal
. So if you want to deal matrices/vectors, you have to convert to a cell array first with num2cell
/mat2cell
. E.g.:
% multiple inputs
[a b] = deal(42,43) % a=2, b=3
[x y z] = deal( zeros(10,1), zeros(10,1), zeros(10,1) )
% vector input
li = [42 43];
lic = num2cell(li);
[a b]=deal(lic{:}) % unforunately can't do num2cell(li){:}
% a=42, b=43
% matrix input
positions = zeros(10,3);
% create cell array, one column each
positionsc = mat2cell(positions,10,[1 1 1]);
[x y z] = deal(positionsc{:})
The first form is nice (deal(x,y,...)
) since it doesn't require you to explicitly make the cell array.
Otherwise I reckon it's not worth using deal
when you have to convert your matrices to cell arrays only to convert them back again: just save the overhead. In any case, it still takes 3 lines: first to define the matrix (e.g. li
), then to convert to cell (lic
), then to do the deal
(deal(lic{:})
).
If you really wanted to reduce the number of lines there's a solution in this question where you just make your own function to do it, repeated here, and modified such that you can define an axis to split over:
function varargout = split(x,axis)
% return matrix elements as separate output arguments
% optionally can specify an axis to split along (1-based).
% example: [a1,a2,a3,a4] = split(1:4)
% example: [x,y,z] = split(zeros(10,3),2)
if nargin < 2
axis = 2; % split along cols by default
end
dims=num2cell(size(x));
dims{axis}=ones([1 dims{axis}]);
varargout = mat2cell(x,dims{:});
end
Then use like this:
[a b] = split([41 42])
[x y z]= split(zeros(10,3), 2) % each is a 10x1 vector
[d e] = split(zeros(2,5), 1) % each is a 1x5 vector
It still does the matrix -> cell -> matrix thing though. If your vectors are small and you don't do it within a loop a million times you should be fine though.
You can extract the values in the list into different variables with
li = [42 43 44];
tmp = num2cell(li);
[a b c] = deal(tmp{:})
a =
42
b =
43
c =
44
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With