48

Here's an example of what I'm looking for:

>> 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?

gnovice
  • 125,304
  • 15
  • 256
  • 359
Benjamin Oakes
  • 12,262
  • 12
  • 65
  • 83
  • 3
    Deal works only if foo is a cell. You have defined foo as a standard array. That's why you got the `??? Cell contents reference from a non-cell array object.` error message. – Justin Peel Feb 25 '10 at 20:17

9 Answers9

46

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
Ramashalanka
  • 8,564
  • 1
  • 35
  • 46
  • 3
    Just a side note, I think you can only get away with not using deal( as in the first example) in Matlab 7+. – Justin Peel Feb 25 '10 at 20:59
  • Interesting. I didn't know that deal is unnecessary nowadays. However, I used mat2cell on purpose, since I assume that the OP might want to separate columns from each other. – Jonas Feb 25 '10 at 21:07
  • 3
    This is really good. But is there any way to have it all on one line? Maybe something like: `[x y] = num2cell(foo){:}` (Sorry, still confused by Matlab quite often.) – Benjamin Oakes Feb 25 '10 at 21:34
  • @Justin: good point, you need version 7.0 (2004) or later. @Jonas: true, `mat2cell` is good if you want to split up in different ways. @Benjamin: I'm not aware of a one line method, unless you use a cell to begin with; you can use `deal(88,12)` if you are starting from scalars. It'd be good if we stuff like `num2cell(foo){:}` for many Matlab commands. – Ramashalanka Feb 25 '10 at 23:26
19

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
Jonas Heidelberg
  • 4,984
  • 1
  • 27
  • 41
jullybobble
  • 191
  • 1
  • 3
8

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
Sander Evers
  • 81
  • 1
  • 1
4

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{:});
Community
  • 1
  • 1
Jonas
  • 74,690
  • 10
  • 137
  • 177
3

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
mtrw
  • 34,200
  • 7
  • 63
  • 71
1

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.

Community
  • 1
  • 1
Victor K
  • 529
  • 2
  • 16
1

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);
Tigliottu
  • 11
  • 1
0

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.

luckydonald
  • 5,976
  • 4
  • 38
  • 58
-1

There is an easier way.

x = foo (1, 1)  
y = foo (1, 2)

Provides

>> x

x =

88

>> y

y =

12

Full documentation at Mathworks.

0x1000001
  • 139
  • 2
  • 10