2014-09-18 4 views
4

Je souhaite affecter les valeurs d'un vecteur de longueur 2 à plusieurs variables. La sortie de la taille() est en mesure de le faire:Affectations de variables multiples Matlab

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

diviser Cependant cela en deux lignes ne fonctionne pas:

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

Quelle est la particularité de la valeur de retour de la taille qui est perdue lorsque il est affecté à une variable?

+2

Jetez un oeil à [ 'varargout'] (http://www.mathworks.com/ help/matlab/ref/varargout.html? refresh = true) et également à ['nargout'] (https://nf.nci.org.au/facilities/software/Matlab/techdoc/ref/nargin.html) – Dan

+0

'size()' est une fonction. Donc quand vous faites 'size ([0 0])', il va dans la fonction interne et retourne deux arguments. Dans le second cas, 'sz' est une variable qui est un vecteur de longueur 2. Maintenant, vous essayez d'assigner une seule variable à deux variables. Cela n'arrivera pas. Vous pouvez écrire votre propre fonction pour le faire. –

+0

regardez ici pour plusieurs affectations variables: http://stackoverflow.com/questions/2740704/is-there-anythinglike-deal-for-normal-matlab-arrays – zinjaai

Répondre

3

La fonction personnalisée que vous avez introduite est assez excessive et utilise des fonctions comme eval qui sont considérées comme une mauvaise pratique. Cela peut être fait beaucoup plus court. C'est tout ce que vous avez besoin:

function [ varargout ] = split(Vector) 

varargout = num2cell(Vector); 

end 

Et à cause de varargout vous avez une liste d'arguments de sortie de longueur variable et vous ne devez modifier votre fonction pour plus argements.

Il fonctionne pour les vecteurs, ainsi que pour les matrices:

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

a = 1 

b = 3 

c = 2 

d = 4 

Si vous ne souhaitez pas la compatibilité de la matrice, inclure une condition et vérifier les dimensions du vecteur d'entrée.

+1

La première phrase mérite à elle seule un +1. Utiliser 'varargout' est la façon la plus simple de le faire. Il y a aussi une approche utilisant une fonction anonyme qui ne nécessite pas de script séparé (voir ma réponse). À moins d'introduire des nargin, nargout, cette solution aura les mêmes pièges que la mienne. La différence est: Vous pouvez introduire de tels tests, alors qu'il est impossible d'utiliser simplement une fonction anonyme. –

+1

@RobertP. J'ai aussi pensé à la solution de deal. Mais l'OP a simplement utilisé 'size 'comme exemple et a réellement besoin de diviser plus de valeurs. C'est plus dur avec 'deal' alors. – thewaywewalk

+0

Je suis d'accord ma fonction est bien trop lourde – portforwardpodcast

4

Les arguments de sortie de Matlab sont intéressants de cette façon. Une fonction peut avoir un nombre variable de sorties en fonction du nombre d'utilisateurs demandés.

Lorsque vous écrivez

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

vous demandez deux arguments de sortie. A l'intérieur de la fonction elle-même correspondrait à la variable nargout égale à 2.

Mais quand vous écrivez

sz = size([0 0]); 

la fonction size reconnaît qu'il est un seul argument de sortie, et vous donne à la fois m et n comme vecteur au lieu de deux sorties singleton. Ce style de comportement est (je pense) généralement inhabituel chez Matlab.

Notez également que Matlab ne permet pas de multiples arguments pour briser les vecteurs:

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

retours Too many output arguments.

0

Il n'est pas quelque chose de spécial au sujet de la taille value.It est juste qu'il traite sz comme un seul argument puisque vous copiez le résultat de la taille et c'est pourquoi il ne peut pas avoir 2 sorties.

Vous obtiendrez la même erreur en utilisant toute autre fonction que définie par 1 sortie, par exemple: [m, n] = cos (0) etc ..

0

J'ai trouvé un moyen de le faire. Grâce à la réponse de Will Robertson, j'ai réalisé que l'écriture d'une fonction était la seule façon d'obtenir ce que je voulais. Voici divisé.

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 

Regardez dans les commentaires pour l'utilisation. J'ai également fait un résumé: https://gist.github.com/esromneb/652fed46ae328b17e104

3

Si pour une raison quelconque ne veulent pas avoir cela dans une fonction séparée, vous pouvez avoir une fonction anonyme renvoie plusieurs sorties comme ceci:

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

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

La fonction deal voit deux arguments du côté gauche et donc produire la sortie correcte. Notez que cette fonction ne répondra pas bien aux mauvaises entrées et sorties. Consultez Loren's blog pour plus d'informations.

2

Vous pouvez le faire transformer sz à un réseau de cellules, puis générer un comma-separated list de ce tableau:

sz_cell = mat2cell(sz(:), ones(numel(sz),1)); 
[m, n] = sz_cell{:}; %// Or [m, n] = deal(sz_cell{:}); 
Questions connexes