Map function in MATLAB?

MatlabFunctional ProgrammingMap Function

Matlab Problem Overview


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)

Matlab Solutions


Solution 1 - Matlab

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.

Solution 2 - Matlab

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

Solution 3 - Matlab

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.

Solution 4 - Matlab

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

Solution 5 - Matlab

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.

Solution 6 - Matlab

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

Solution 7 - Matlab

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser121550View Question on Stackoverflow
Solution 1 - MatlabgnoviceView Answer on Stackoverflow
Solution 2 - MatlabkwatfordView Answer on Stackoverflow
Solution 3 - MatlabdocView Answer on Stackoverflow
Solution 4 - MatlabFoo BaraView Answer on Stackoverflow
Solution 5 - MatlabDimaView Answer on Stackoverflow
Solution 6 - MatlabDarioView Answer on Stackoverflow
Solution 7 - MatlabTallBrianLView Answer on Stackoverflow