在MATLAB中的映射函数?
我有点惊讶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)
简短的回答:内置的函数ARRAYFUN完成了你的映射函数对数值数组的作用:
>> y = arrayfun(@(x) x^2,1:10) y = 1 4 9 16 25 36 49 64 81 100
还有另外两个内置函数的行为类似: CELLFUN (对单元arrays的元素进行操作)和STRUCTFUN (对结构的每个字段进行操作)。
但是,如果利用向量化,通常不需要这些函数,特别是使用基于元素的算术运算符 。 对于你给的例子,一个vector化的解决scheme是:
>> x = 1:10; >> y = x.^2 y = 1 4 9 16 25 36 49 64 81 100
有些操作会自动跨元素操作(比如向向量添加标量值),而其他操作符则有特殊的元素操作语法(在操作符之前用“。”表示)。 MATLAB中的许多函数被devise为使用基于元素的操作对向量和matrix参数进行操作,因此不需要映射函数。
总结一下,下面是一些不同的方法来排列数组中的每个元素:
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是最明智的select。
除了vector和元素操作之外,还有cellfun
用于映射单元格arrays上的函数。 例如:
cellfun(@upper, {'a', 'b', 'c'}, 'UniformOutput',false) ans = 'A' 'B' 'C'
如果'UniformOutput'为真(或不提供),它将尝试根据单元格数组的大小连接结果,所以
cellfun(@upper, {'a', 'b', 'c'}) ans = ABC
一个相当简单的解决scheme,使用Matlab的vector化将是:
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中的值的引用并且没有副本。
如果matlab没有内置的map函数,可能是因为效率的考虑。 在你的实现中,你正在使用一个循环遍历列表中的元素,这在matlab世界中通常是不被赞赏的。 大多数内置的matlab函数都是“vector化”的,也就是说,在整个数组上调用一个函数会更高效,而不是自己遍历它,并调用每个元素的函数。
换句话说,这个
a = 1:10; a.^2
比这更快
a = 1:10; map(@(x)x^2, a)
假设你定义了地图。
看起来,如果需要的结果是一个函数数组,内置的arrayfun不起作用:例如:map(@(x)[xx ^ 2 x ^ 3],1:10)
下面的一些小小的mod可以让这个工作更好:
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
您不需要map
因为应用于值列表的标量函数应用于每个值,因此其工作原理与map
类似。 你试一试
l = 1:10 f = @(x) x + 1 f(l)
在你的具体情况下,你甚至可以写
l.^2
如前面的答案中所述的向量化解决scheme可能是速度的最佳解决scheme。 Vectorizing也是非常非常好的。
用这个说Matlab现在有一个Map容器类。