Как мне сделать множественное назначение в MATLAB?

41

Вот пример того, что я ищу:

>> foo = [88, 12];
>> [x, y] = foo;

Я бы ожидал чего-то подобного:

>> x

x =

    88

>> y

y =

    12

Но вместо этого я получаю такие ошибки, как:

??? Too many output arguments.

Я думал, что deal() может это сделать, но, похоже, работает только с ячейками.

>> [x, y] = deal(foo{:});
??? Cell contents reference from a non-cell array object.

Как я могу решить свою проблему? Должен ли я постоянно индексировать 1 и 2, если я хочу иметь дело с ними отдельно?

  • 3
    Сделка работает, только если foo является клеткой. Вы определили foo как стандартный массив. Вот почему вы получили ??? Cell contents reference from a non-cell array object. сообщение об ошибке.
Теги:
arrays
variables
variable-assignment

9 ответов

40
Лучший ответ

Вам вообще не нужно deal (отредактируйте: для Matlab 7.0 или новее), и для вашего примера вам не нужно mat2cell; вы можете использовать num2cell без каких-либо других аргументов::

foo = [88, 12];
fooCell = num2cell(foo);
[x y]=fooCell{:}

x =

    88


y =

    12

Если вы хотите использовать deal по какой-либо другой причине, вы можете:

foo = [88, 12];
fooCell = num2cell(foo);
[x y]=deal(fooCell{:})

x =

    88


y =

    12
  • 3
    Просто примечание, я думаю, что вы можете избежать неприятностей с использованием сделки (как в первом примере) в Matlab 7+.
  • 0
    Интересно. Я не знал, что в настоящее время сделка не нужна. Однако я специально использовал mat2cell, поскольку я предполагаю, что OP может захотеть отделить столбцы друг от друга.
Показать ещё 2 комментария
11

Обратите внимание, что deal принимает "список" в качестве аргумента, а не массив ячеек. Итак, следующее работает так, как ожидалось:

> [x,y] = deal(88,12)
x = 88

y = 12

Синтаксис c{:} преобразует массив ячеек в список, а список представляет собой значения, разделенные запятыми, как в аргументах функции. Это означает, что вы можете использовать синтаксис c{:} как аргумент для других функций, чем deal. Чтобы убедиться в этом, попробуйте следующее:

> z = plus(1,2)
z = 3

> c = {1,2};
> z = plus(c{:});
z = 3
7

Чтобы использовать решение num2cell в одной строке, определите вспомогательную функцию list:

function varargout = list(x)
% return matrix elements as separate output arguments
% example: [a1,a2,a3,a4] = list(1:4)

varargout = num2cell(x);

end
  • 0
    не будет ли пример [a1,a2,a3,a4] = list(1:4) вызвать Too many output arguments ?
4

Что mtrw. В принципе, вы хотите использовать сделку с массивом ячеек (хотя сделка (88,12) также работает).

Предполагая, что вы начинаете с массива foo, который является n-by-2, и вы хотите назначить первый столбец x, а второй - y, вы делаете следующее:

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{:});
1

Существует более простой способ.

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

Обеспечивает

>> x

x =

88

>> y

y =

12

Полная документация на Mathworks.

1

Возможно, вы ищете

>>> foo = [88, 12];
>>> [x, y] = deal(foo(1), foo(2))

в результате чего

x = 
    88

y = 
    12

Итак, у вас есть рабочий однострочный.

  • 0
    Почему отрицательный голос?
1

Я не могу комментировать другие ответы, поэтому отдельное дополнение.

вы можете использовать сделку (88,12), если вы начинаете с скаляров

deal также может использоваться как однострочный для нескалляров, конечно, если вы уже имеете их в отдельных переменных, скажите:

a = 123;
b = rand(3);
c = {a, b};
d = struct('field','val')

и теперь вы обрабатываете их одной строкой:

>> [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'

Однако, если они упакованы в одну переменную, вы можете только deal их, если они находятся в массиве ячеек или структуры - с deal(X{:}) для массива ячеек и deal(S.field) для массива структуры. (В последнем случае обрабатывается только одно поле, но из всех структур в массиве.) С Matlab v.7 + вы можете использовать X{:} и S.field без deal, как указано в других ответах.

1

DEAL действительно полезен и действительно запутан. Я думаю, что foo должен быть массивом ячеек. Кажется, что в Octave работает, если я правильно помню, что он будет работать и в MATLAB:

> foo = {88, 12}
foo =

{
  [1,1] =  88
  [1,2] =  12
}

> [x,y] = deal(foo{:})
x =  88
y =  12
0

Создайте функцию arr2vars для удобства

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

Вы можете использовать его тогда, как это

[~,roi] = imcrop(im);
[x,w,y,h] = arr2vars(roi);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню