103

我有点惊讶 MATLAB 没有 Map 功能,所以我自己拼凑了一个,因为它是我不能没有的东西。那里有更好的版本吗?那里有一个我缺少的用于 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

用法例如

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

7 回答 7

137

简短的回答:内置函数与您的函数对数值数组arrayfun所做的完全相同:map

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

     1     4     9    16    25    36    49    64    81   100

还有另外两个类似的内置函数:(cellfun对元胞数组的元素进行操作)和structfun(对结构的每个字段进行操作)。

但是,如果您利用向量化,特别是使用逐元素算术运算符,这些函数通常不是必需的。对于您给出的示例,矢量化解决方案将是:

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

     1     4     9    16    25    36    49    64    81   100

一些操作将自动跨元素进行操作(例如将标量值添加到向量),而其他操作符具有用于元素操作的特殊语法(由.操作符之前的 a 表示)。MATLAB 中的许多内置函数旨在使用逐元素运算(通常应用于给定维度,例如)对向量和矩阵参数进行运算summean因此不需要映射函数。

总而言之,这里有一些对数组中每个元素求平方的不同方法:

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

当然,对于这样一个简单的操作,选项#1 是最明智(也是最有效)的选择。

于 2009-06-11T19:48:38.483 回答
10

除了向量和元素操作之外,还有cellfun在元胞数组上映射函数。例如:

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

如果 'UniformOutput' 为真(或未提供),它将尝试根据元胞数组的维度连接结果,因此

cellfun(@upper, {'a', 'b', 'c'})
ans =
ABC
于 2009-06-11T20:17:05.153 回答
2

一个相当简单的解决方案,使用 Matlab 的矢量化将是:

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

现在,键入

c( b ) = a

返回

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

c( b ) 是对大小为 5 的向量的引用,其中 c 的元素位于 b 给定的索引处。现在,如果你为这个参考向量赋值,c 中的原始值将被覆盖,因为 c( b ) 包含对 c 中值的引用并且没有副本。

于 2011-11-17T14:09:29.340 回答
1

如果需要的结果是函数数组,则内置 arrayfun 似乎不起作用:例如: map(@(x)[xx^2 x^3],1:10)

下面的轻微修改使这项工作更好:

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
于 2012-04-26T10:39:17.223 回答
0

如果 matlab 没有内置 map 函数,可能是出于效率考虑。在您的实现中,您使用循环来迭代列表的元素,这在 matlab 世界中通常是不受欢迎的。大多数内置的matlab 函数都是“矢量化的”,即在整个数组上调用函数比自己迭代它并为每个元素调用函数更有效。

换句话说,这


a = 1:10;
a.^2

比这快得多


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

假设您对地图的定义。

于 2009-06-11T19:48:34.597 回答
0

您不需要map,因为应用于值列表的标量函数应用于每个值,因此与map. 试试看嘛

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

f(l)

在您的特定情况下,您甚至可以编写

l.^2
于 2009-06-11T19:54:21.183 回答
-1

如前面的答案中所述,矢量化解决方案可能是速度的最佳解决方案。Vectorizing也很Matlaby,感觉不错。

话虽如此,Matlab 现在确实有一个 Map 容器类。

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

于 2014-05-02T21:34:05.013 回答