2014-09-18 2 views
4

Я хотел бы присвоить значения в векторе длины 2 нескольким переменным. Выход размера() в состоянии сделать это:Множественные присваивания Matlab

% works 
[m,n] = size([0 0]); 

Однако разделив ее на две линии не работает:

sz = size([0 0]); 
[m,n] = sz; 
% returns: 
% ??? Too many output arguments. 

Что особенного значения, возвращенного размера, который теряется, когда он присваивается переменной?

+2

взглянуть на [ 'varargout'] (http://www.mathworks.com/ help/matlab/ref/varargout.html? refresh = true), а также в ['nargout'] (https://nf.nci.org.au/facilities/software/Matlab/techdoc/ref/nargin.html) – Dan

+0

'size()' является функцией. Поэтому, когда вы выполняете 'size ([0 0])', он входит во внутреннюю функцию и возвращает два аргумента. Во втором случае 'sz' является переменной, которая является вектором длины 2. Теперь вы пытаетесь присвоить одну переменную двум переменным. Этого не произойдет. Вы можете написать свою собственную функцию для этого. –

+0

смотрите здесь для нескольких присваиваний переменных: http://stackoverflow.com/questions/2740704/is-there-anything-like-deal-for-normal-matlab-arrays – zinjaai

ответ

3

Пользовательская функция, которую вы ввели, является излишним и использует такие функции, как eval, которые считаются плохой практикой. Это можно сделать гораздо короче. Это все, что вам нужно:

function [ varargout ] = split(Vector) 

varargout = num2cell(Vector); 

end 

И из-за varargout у вас есть список выходного аргумента переменной длины и вам не нужно редактировать функцию для более argements.

Он работает для векторов, а также для матриц:

[a,b,c,d] = split([1,2;3,4]) 

a = 1 

b = 3 

c = 2 

d = 4 

Если вам не нравится совместимость матрицы, включают в себя состояние и проверить размеры входного вектора.

+1

Первое предложение само по себе заслуживает +1. Использование 'varargout' - самый плавный способ сделать это. Существует также подход, использующий анонимную функцию, которая не требует отдельного скрипта (см. Мой ответ). Если вы не представите какие-либо наргинские, nargout чеки, это решение будет иметь те же проблемы, что и мои. Разница заключается в следующем: вы можете ввести такие тесты, в то время как невозможно использовать только анонимную функцию. –

+1

@RobertP. Я тоже думал о решении сделки. Но OP, очевидно, просто использовал «размер» в качестве примера и на самом деле нужно разделить больше значений. Его сложнее с «сделкой». – thewaywewalk

+0

Я согласен, что моя функция - это переполнение – portforwardpodcast

4

Выходные аргументы Matlab интересны таким образом. Функция может иметь переменное количество выходов в зависимости от того, сколько просил пользователь.

Когда вы пишете

[m,n] = size([0 0]); 

вы запрашиваете два выходных параметра. Внутри самой функции это будет соответствовать переменной nargout, равной 2.

Но когда вы пишете

sz = size([0 0]); 

функция size признает, что это единственный выходной аргумент, и дает вам как m и n как вектор вместо двух одноэлементных выходов. Этот стиль поведения (я думаю) вообще не встречается в Matlab.

Также обратите внимание, что Matlab не позволяет несколько аргументов, чтобы разбить векторы:

x = [1 1] 
[y,z] = x 

возвращается Too many output arguments.

0

Это не что-то особенное о размере value.It только, что речь идет sz как единственный аргумент, так как вы копируете ему результат размера, и поэтому он не может иметь 2 выхода.

вы получите ту же ошибку, используя любую другую функцию, которая, определяемую 1 выход, например: [т, п] = соз (0) и т.д ..

0

я понял, способ сделать это. Благодаря ответу Уилла Робертсона я понял, что написать функцию - единственный способ получить то, что я хочу. Здесь расколото.

function [ o1, o2, o3, o4, o5, o6, o7, o8 ] = split(v) 
%SPLIT Splits a vector of bounded length into individual return variables. 
% Split() can handle arbitrarily long input vectors, but only a fixed 
% number of output variables. @benathon 
% 
% Usage: 
% vec = [1 2 3 4 5]; 
% [a,b,c,d,e] = split(vec); 
% [f,g]  = split(vec); 

% If you would like to upgrade split() to handle more output variables, 
% simply add more output variables to the function definition and 
% then change this variable 
maxout = 8; 

[~,n] = size(v); 

if n < nargout 
    error('input vector too short for number of output arguments'); 
end 

% we only need to assign this many output variables 
iterations = min(n,nargout); 


% Matlab catches "Too many output arguments." before we can 
%if(iterations > maxout) 
% error('Too many output, edit split.m to easily upgrade'); 
%end 


i = 1; 
while i <= iterations 
    expression = sprintf('o%d=v(%d);', i, i); 
    eval(expression); 
    i = i + 1; 
end 

Посмотрите комментарии к использованию. Я также сделал суть: https://gist.github.com/esromneb/652fed46ae328b17e104

3

Если вы по каким-то причинам не хотите иметь это в отдельной функции, вы можете иметь анонимную функцию возвращает несколько выходов, как это:

split = @(x) deal(x(1), x(2)) 
A = zeros(5,3) 
sz = size(A) 

[x, y] = split(sz) 
    x = 5 
    y = 3 

deal функция видит две левых боковые аргументов и, таким образом, выведите правильный результат. Обратите внимание, что эта функция не будет хорошо реагировать на неправильный ввод и вывод. За дополнительной информацией обращайтесь к Loren's blog.

2

Вы могли бы сделать это преобразование sz в массив ячеек, а затем генерируют comma-separated list из этого массива:

sz_cell = mat2cell(sz(:), ones(numel(sz),1)); 
[m, n] = sz_cell{:}; %// Or [m, n] = deal(sz_cell{:}); 
Смежные вопросы