MATLAB 中的映射函数?

发布于 2024-07-24 07:46:39 字数 395 浏览 12 评论 0原文

我有点惊讶 MATLAB 没有 Map 函数,所以我自己编写了一个 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)

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

自由如风 2024-07-31 07:46:40

简短的答案:内置函数 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

某些操作将自动跨元素进行操作(例如向向量添加标量值),而其他运算符则具有用于按元素操作的特殊语法(由 .< 表示) /code> 位于运算符之前)。 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是最明智(也是最有效)的选择。

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.

温馨耳语 2024-07-31 07:46:40

除了向量和逐元素运算之外,还有用于将函数映射到元胞数组的 cellfun 。 例如:

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

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

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

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
空心空情空意 2024-07-31 07:46:40

使用 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

returns

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

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

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.

初心 2024-07-31 07:46:40

如果需要的结果是函数数组,则内置 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

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
聊慰 2024-07-31 07:46:40

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

换句话说,这


a = 1:10;
a.^2

要快得多。


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

比假设您定义地图

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.

筱武穆 2024-07-31 07:46:40

您不需要 map,因为应用于值列表的标量函数会应用于每个值,因此其工作方式与 map 类似。 只是尝试

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

f(l)

在你的具体情况下,你甚至可以写

l.^2

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
温柔嚣张 2024-07-31 07:46:40

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

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

请参阅 http://www.mathworks.com/help/matlab/map-containers。 html

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文