2009-06-11 25 views
85

Estoy un poco sorprendido de que MATLAB no tenga una función de Mapa, así que la pirateé yo mismo, ya que es algo de lo que no puedo vivir. ¿Hay una mejor versión por ahí? ¿Existe una biblioteca de programación funcional algo estándar para MATLAB por ahí que me falta?Función de mapa en MATLAB?

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 

uso sería p. Ej.

map(@(x)x^2,1:10) 
+11

Lección # 1 pasando de otros idiomas a Matlab: No utilice los bucles, que son algunos órdenes de magnitud más lento que una solución vectorizado. – CookieOfFortune

+1

¿Qué hay de la recursión? – Dario

+15

Con la introducción del JIT, para los bucles no se aplica la penalización que alguna vez tuvieron. – MatlabDoug

Respuesta

1

Si matlab no tiene una función integrada en el mapa, podría deberse a consideraciones de eficiencia. En su implementación, está utilizando un bucle para iterar sobre los elementos de la lista, lo que generalmente es desaprobado en el mundo de los matlab. La mayoría de las funciones incorporadas de matlab están "vectorizadas", i. mi. es más eficiente llamar a una función en una matriz completa que iterar sobre ella y llamar a la función para cada elemento.

En otras palabras, este


a = 1:10; 
a.^2 

es mucho más rápido que esto


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

asumiendo que su definición del mapa.

+1

Creo que su punto no era que él quisiera necesariamente hacerlo en bucle, sino simplemente que se especificara como el resultado de la matriz de resultados al aplicar la función suministrada a los elementos correspondientes de la matriz suministrada. No sé mucho de matlab, pero parece que arrayfun hace el trabajo. –

+1

La mayoría de las funciones y operadores de Matlab ya lo hacen: operan en cada elemento de la matriz de entrada y devuelven una matriz de resultados correspondiente. – Dima

123

La respuesta corta: la función incorporada ARRAYFUN hace exactamente lo que hace su mapa de funciones para las matrices numéricas:

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

    1  4  9 16 25 36 49 64 81 100 

Hay otras dos funciones integradas que se comportan de manera similar: CELLFUN (que opera en elementos de matrices de celdas) y STRUCTFUN (que opera en cada campo de una estructura).

Sin embargo, estas funciones a menudo no son necesarios si se toma ventaja de vectorización, utilizando específicamente elemento a elemento arithmetic operators. Para el ejemplo que dio, una solución vectorizado sería:

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

    1  4  9 16 25 36 49 64 81 100 

Algunas operaciones funcionarán automáticamente a través de los elementos (como la adición de un valor escalar de un vector), mientras que otros operadores tienen una sintaxis especial para la operación de elemento a elemento (denotado por un "." antes del operador). Muchas funciones en MATLAB están diseñadas para operar en vectores y argumentos de matriz usando operaciones de elementos, y por lo tanto no requieren funciones de mapa.

Para resumir, he aquí algunas maneras diferentes para al cuadrado cada elemento de una matriz:

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 

Por supuesto, para una operación tan sencilla, la opción # 1 es la elección más sensata.

+2

¡Debe tenerse en cuenta que la opción 1 no solo es más simple, sino también más rápida (en comparación con la opción 3, 2 debería ser muy similar a 1)! –

0

No necesita map ya que una función escalar que se aplica a una lista de valores se aplica a cada uno de los valores y por lo tanto funciona de manera similar a map. Solo trata

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

f(l) 

En su caso particular, incluso se podría escribir

l.^2 
+9

-1: Eso no es verdad en realidad. Matlab no tiene un sistema de tipos lo suficientemente fuerte como para especificar funciones escalares. Se llama f con el vector y se realiza una adición de vector único en su ejemplo. Para verificar esto, perfile su muestra de código ("perfil activado" antes de ejecutar el código, luego "perfil de informe" después de él). Verás que hay una sola llamada a f. –

10

Además de vectores y operaciones elemento a elemento, también hay cellfun para las funciones de mapeo más de matrices de células.Por ejemplo:

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

Si 'UniformOutput' es verdadera (o no proporcionado), intentará para concatenar los resultados de acuerdo a las dimensiones de la serie de células, por lo

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

Una solución bastante simple , mediante la vectorización de Matlab sería:

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 

Ahora, al escribir

c(b) = a 

rendimientos

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

c (B) es una referencia a un vector de tamaño 5 con los elementos de c en los índices dados por b. Ahora, si asigna valores a este vector de referencia, los valores originales en c se sobrescriben, ya que c (b) contiene referencias a los valores en c y no a las copias.

1

Parece que la incorporada en el arrayfun no funciona si el resultado que se necesita es una matriz de función: por ejemplo: mapa (@ (x) [xx^2 x^3], 1: 10)

ligeras modificaciones por debajo de hacer que esto funcione mejor:

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 
+5

[ARRAYFUN] (http://www.mathworks.com/help/techdoc/ref/arrayfun.html) funcionaría para su ejemplo, solo tendría que incluir los argumentos de entrada '..., 'UniformOutput', falso); 'para crear una salida de matriz de celdas que contenga sus matrices, luego formatee y combínelas como desee en una matriz que no sea una celda. – gnovice

-1

vectorización de la solución como se describe en las respuestas anteriores es probablemente la mejor solución para la velocidad. Vectorizar también es muy Matlaby y se siente bien.

Dicho esto, Matlab ahora tiene una clase de contenedor de mapas.

Ver http://www.mathworks.com/help/matlab/map-containers.html

+0

Op está hablando de la función de orden superior, es decir, 'cellfun' et al., No tablas hash o pares clave-valor. –