2012-01-28 4 views
2

Comment appliquer une fonction qui renvoie une sortie non scalaire à des tableaux en utilisant arrayfun?Application d'une fonction sur un tableau qui renvoie des sorties de taille différente de façon vectorielle

Par exemple - Comment peut vectoriser le code suivant?

array = magic(5); 
A = cell(size(array)); 
for i=1:5 
    for j=1:5 
     A{i,j} = 1:array(i,j); 
    end 
end 

Cette tentative naïve de vectorisation ne fonctionne pas, parce que la sortie n'est pas un scalaire

array = magic(5); 
result = arrayfun(@(x)(1:x),array); 

Répondre

6

Il existe 2 méthodes pour y parvenir:

Il est possible de définir « UniformOutput » à faux. Ensuite, le résultat est un tableau de cellules.

result = arrayfun(@(x)(1:x),array,'UniformOutput',false); 

Mais il ya une bonne astuce que j'ai trouvé aujourd'hui, la fonction elle-même peut retourner une cellule. Cela supprime le besoin de taper 'UniformOutput',false chaque fois.

result = arrayfun(@(x){1:x},array) 

Qu'est-ce que vraiment intéressant ici que je n'ai pas taper @(X)({1:x}) mais je peux définir seulement en utilisant Brassards bouclés @(X){1:x}

Modifier (1): Comme @Jonas correctement les points dehors, il n'est pas étonnant que les brassards réguliers () ne sont pas nécessaires, car ils sont facultatifs. Par exemple, @(x) x+1 est une syntaxe valide.

Modifier (2): Il existe une petite différence entre l'utilisation de la méthode des brassards bouclés ou UniformOutput,false. Lorsque le tableau d'entrée est vide, leur comportement est différent.

+5

Vous ne devez jamais les parenthèses autour de la fonction. Mais cela aide beaucoup avec la visibilité. De plus, 'arrayfun' ne vectorise pas vraiment le code, il cache juste la boucle (et permettra à Matlab de multi-threader, si cela en vaut la peine). Notez que le "trick" de la cellule est très utile avec 'accumarray' qui n'a pas l'option' uniformOutput'. – Jonas

+1

Voilà ce que le SO est pour :) – Jonas

1

En plus de la réponse de Andrey Je veux noter qu'il semble que la première approche, en utilisant l'option UniformOutput, est légèrement plus rapide:

>> tic; cellfun(@(x) {single(x)}, data); toc; 
Elapsed time is 0.031817 seconds. 

>> tic; cellfun(@(x) single(x), data,'UniformOutput',0); toc; 
Elapsed time is 0.025526 seconds. 
Questions connexes