How do I do multiple assignment in MATLAB?
Here's an example of what I'm looking for:
>开发者_如何学C;> foo = [88, 12];
>> [x, y] = foo;
I'd expect something like this afterwards:
>> x
x =
88
>> y
y =
12
But instead I get errors like:
??? Too many output arguments.
I thought deal()
might do it, but it seems to only work on cells.
>> [x, y] = deal(foo{:});
??? Cell contents reference from a non-cell array object.
How do I solve my problem? Must I constantly index by 1 and 2 if I want to deal with them separately?
You don't need deal
at all (edit: for Matlab 7.0 or later) and, for your example, you don't need mat2cell
; you can use num2cell
with no other arguments::
foo = [88, 12];
fooCell = num2cell(foo);
[x y]=fooCell{:}
x =
88
y =
12
If you want to use deal
for some other reason, you can:
foo = [88, 12];
fooCell = num2cell(foo);
[x y]=deal(fooCell{:})
x =
88
y =
12
Note that deal
accepts a "list" as argument, not a cell array. So the following works as expected:
> [x,y] = deal(88,12)
x = 88
y = 12
The syntax c{:}
transforms a cell array in a list, and a list is a comma separated values, like in function arguments. Meaning that you can use the c{:}
syntax as argument to other functions than deal
. To see that, try the following:
> z = plus(1,2)
z = 3
> c = {1,2};
> z = plus(c{:});
z = 3
To use the num2cell
solution in one line, define a helper function list
:
function varargout = list(x)
% return matrix elements as separate output arguments
% example: [a1,a2,a3,a4] = list(1:4)
varargout = num2cell(x);
end
What mtrw said. Basically, you want to use deal with a cell array (though deal(88,12) works as well).
Assuming you start with an array foo that is n-by-2, and you want to assign the first column to x and the second to y, you do the following:
foo = [88,12;89,13;90,14];
%# divide the columns of foo into separate cells, i.e. do mat2cell(foo,3,[1,1])
fooCell = mat2cell(foo,size(foo,1),ones(size(foo,2),1));
[x,y] = deal(fooCell{:});
DEAL is really useful, and really confusing. foo
needs to be a cell array itself, I believe. The following seems to work in Octave, if I remember correctly it will work in MATLAB as well:
> foo = {88, 12}
foo =
{
[1,1] = 88
[1,2] = 12
}
> [x,y] = deal(foo{:})
x = 88
y = 12
I cannot comment other answers, so separate addition.
you can use deal(88,12) if you are starting from scalars
deal
can be used as a one-liner for non-scalars as well, of course if you already have them in separate variables, say:
a = 123;
b = rand(3);
c = {a, b};
d = struct('field','val')
and now you deal them with one line:
>> [x,y,z,w] = deal(a,b,c,d)
x =
123
y =
0.6370 0.2165 0.6711
0.2945 0.8803 0.2705
0.7633 0.1537 0.0767
z =
[123] [3x3 double]
w =
field: 'val'
However, if they are packed in one variable, you can only deal
them if they are in a cell or structure array - with deal(X{:})
for cell array and deal(S.field)
for structure array. (In the latter case only one field is dealt, but from all structures in array.) With Matlab v.7+ you can use X{:}
and S.field
without deal
, as noted in other answers.
Create a function arr2vars for convenience
function varargout = arr2vars(arr)
% Distribute elements over variables
N = numel(arr);
if nargout ~= N
error('Number of outputs does not match number of elements')
end
for k = 1:N
varargout{k} = arr(k);
end
You can use it then like this
[~,roi] = imcrop(im);
[x,w,y,h] = arr2vars(roi);
You might be looking for
>>> foo = [88, 12];
>>> [x, y] = deal(foo(1), foo(2))
resulting in
x =
88
y =
12
So you have a working one-liner.
There is an easier way.
x = foo (1, 1)
y = foo (1, 2)
Provides
>> x
x =
88
>> y
y =
12
Full documentation at Mathworks.
精彩评论