Map function in MATLAB?

时光总嘲笑我的痴心妄想 提交于 2019-11-26 10:15:40

问题


I\'m a little surprised that MATLAB doesn\'t have a Map function, so I hacked one together myself since it\'s something I can\'t live without. Is there a better version out there? Is there a somewhat-standard functional programming library for MATLAB out there that I\'m missing?

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

usage would be e.g.

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

回答1:


The short answer: the built-in function arrayfun does exactly what your map function does for numeric arrays:

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

     1     4     9    16    25    36    49    64    81   100

There are two other built-in functions that behave similarly: cellfun (which operates on elements of cell arrays) and structfun (which operates on each field of a structure).

However, these functions are often not necessary if you take advantage of vectorization, specifically using element-wise arithmetic operators. For the example you gave, a vectorized solution would be:

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

     1     4     9    16    25    36    49    64    81   100

Some operations will automatically operate across elements (like adding a scalar value to a vector) while others operators have a special syntax for element-wise operation (denoted by a . before the operator). Many built-in functions in MATLAB are designed to operate on vector and matrix arguments using element-wise operations (often applied to a given dimension, such as sum and mean for example), and thus don't require map functions.

To summarize, here are some different ways to square each element in an array:

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

Of course, for such a simple operation, option #1 is the most sensible (and efficient) choice.




回答2:


In addition to vector and element-wise operations, there's also cellfun for mapping functions over cell arrays. For example:

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

If 'UniformOutput' is true (or not provided), it will attempt to concatenate the results according to the dimensions of the cell array, so

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



回答3:


A rather simple solution, using Matlab's vectorization would be:

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

Now, typing

c( b ) = a

returns

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

c( b ) is a reference to a vector of size 5 with the elements of c at the indices given by b. Now if you assing values to this reference vector, the original values in c are overwritten, since c( b ) contains references to the values in c and no copies.




回答4:


It seems that the built-in arrayfun doesn't work if the result needed is an array of function: eg: map(@(x)[x x^2 x^3],1:10)

slight mods below make this work better:

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:


If matlab does not have a built in map function, it could be because of efficiency considerations. In your implementation you are using a loop to iterate over the elements of the list, which is generally frowned upon in the matlab world. Most built-in matlab functions are "vectorized", i. e. it is more efficient to call a function on an entire array, than to iterate over it yourself and call the function for each element.

In other words, this


a = 1:10;
a.^2

is much faster than this


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

assuming your definition of map.




回答6:


You don't need map since a scalar-function that is applied to a list of values is applied to each of the values and hence works similar to map. Just try

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

f(l)

In your particular case, you could even write

l.^2



回答7:


Vectorizing the solution as described in the previous answers is the probably the best solution for speed. Vectorizing is also very Matlaby and feels good.

With that said Matlab does now have a Map container class.

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



来源:https://stackoverflow.com/questions/983163/map-function-in-matlab

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!