开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜