web-dev-qa-db-fra.com

Fonction de carte dans MATLAB?

Je suis un peu surpris que MATLAB n'ait pas de fonction Map, alors j'en ai piraté une moi-même car c'est quelque chose dont je ne peux pas me passer. Existe-t-il une meilleure version? Existe-t-il une bibliothèque de programmation fonctionnelle quelque peu standard pour MATLAB qui me manque?

function results = map(f,list)
% why doesn't MATLAB have a Map function?
results = zeros(1,length(list));
for k = 1:length(list)
    results(1,k) = f(list(k));
end

end

l'utilisation serait par exemple.

map( @(x)x^2,1:10)
95
user121550

La réponse courte: la fonction intégrée arrayfun fait exactement ce que fait votre fonction map pour les tableaux numériques:

>> y = arrayfun(@(x) x^2, 1:10)
y =

     1     4     9    16    25    36    49    64    81   100

Il existe deux autres fonctions intégrées qui se comportent de la même manière: cellfun (qui fonctionne sur les éléments des tableaux de cellules) et structfun (qui opère sur chaque champ d'une structure).

Cependant, ces fonctions ne sont souvent pas nécessaires si vous profitez de la vectorisation, en particulier en utilisant les éléments opérateurs arithmétiques . Pour l'exemple que vous avez donné, une solution vectorisée serait:

>> x = 1:10;
>> y = x.^2
y =

     1     4     9    16    25    36    49    64    81   100

Certaines opérations fonctionneront automatiquement sur plusieurs éléments (comme l'ajout d'une valeur scalaire à un vecteur) tandis que d'autres opérateurs ont une syntaxe spéciale pour les opérations par élément (désignée par un . devant l'opérateur). De nombreuses fonctions intégrées dans MATLAB sont conçues pour fonctionner sur des arguments vectoriels et matriciels à l'aide d'opérations élémentaires (souvent appliquées à une dimension donnée, telles que sum et mean par exemple), et ne nécessitent donc pas de fonctions de carte.

Pour résumer, voici différentes façons de mettre en carré chaque élément d'un tableau:

x = 1:10;       % Sample array
f = @(x) x.^2;  % Anonymous function that squares each element of its input

% Option #1:
y = x.^2;  % Use the element-wise power operator

% Option #2:
y = f(x);  % Pass a vector to f

% Option #3:
y = arrayfun(f, x);  % Pass each element to f separately

Bien sûr, pour une opération aussi simple, l'option # 1 est le choix le plus judicieux (et efficace).

130
gnovice

En plus des opérations vectorielles et élémentaires, il existe également cellfun pour mapper les fonctions sur les tableaux de cellules. Par exemple:

cellfun(@upper, {'a', 'b', 'c'}, 'UniformOutput',false)
ans = 
    'A'    'B'    'C'

Si 'UniformOutput' est vrai (ou non fourni), il tentera de concaténer les résultats en fonction des dimensions du tableau de cellules, donc

cellfun(@upper, {'a', 'b', 'c'})
ans =
ABC
10
kwatford

Une solution assez simple, utilisant la vectorisation de Matlab serait:

a = [ 10 20 30 40 50 ]; % the array with the original values
b = [ 10 8 6 4 2 ]; % the mapping array
c = zeros( 1, 10 ); % your target array

Maintenant, en tapant

c( b ) = a

résultats

c = 0    50     0    40     0    30     0    20     0    10

c (b) est une référence à un vecteur de taille 5 avec les éléments de c aux indices donnés par b. Maintenant, si vous attribuez des valeurs à ce vecteur de référence, les valeurs d'origine dans c sont écrasées, car c (b) contient des références aux valeurs dans c et aucune copie.

2
doc

Il semble que le arrayfun intégré ne fonctionne pas si le résultat requis est un tableau de fonctions: par exemple: map (@ (x) [x x ^ 2 x ^ 3], 1: 10)

de légers mods ci-dessous améliorent ce travail:

function results = map(f,list)
% why doesn't MATLAB have a Map function?
for k = 1:length(list)
    if (k==1)
        r1=f(list(k));
        results = zeros(length(r1),length(list));
        results(:,k)=r1;
    else
        results(:,k) = f(list(k));

    end;
end;
end
1
Foo Bara

Si matlab n'a pas de fonction de carte intégrée, cela peut être dû à des considérations d'efficacité. Dans votre implémentation, vous utilisez une boucle pour parcourir les éléments de la liste, ce qui est généralement mal vu dans le monde matlab. La plupart des fonctions matlab intégrées sont "vectorisées", i. e. il est plus efficace d'appeler une fonction sur un tableau entier que de le parcourir vous-même et d'appeler la fonction pour chaque élément.

En d'autres termes, cette


a = 1:10;
a.^2

est beaucoup plus rapide que cela


a = 1:10;
map(@(x)x^2, a)

en supposant votre définition de la carte.

0
Dima

Vous n'avez pas besoin de map car une fonction scalaire qui est appliquée à une liste de valeurs est appliquée à chacune des valeurs et fonctionne donc de manière similaire à map. Essayez

l = 1:10
f = @(x) x + 1

f(l)

Dans votre cas particulier, vous pourriez même écrire

l.^2
0
Dario