MATLAB - 映射函数
MATLAB - 将函数应用于数组元素
Section titled “MATLAB - 将函数应用于数组元素”一个常见的编程任务是对数组中的每个元素应用特定的操作或函数。虽然许多语言使用 map 函数来完成此任务,但 MATLAB 鼓励一种更高效、更易读的方法,称为向量化(vectorization)。在向量化不可行的情况下,MATLAB 提供了 arrayfun 和 cellfun 函数。
最佳实践:向量化
Section titled “最佳实践:向量化”向量化是将基于循环、面向标量的代码重写为使用 MATLAB 的矩阵和向量运算的过程。它更快、更符合 MATLAB 习惯,因为 MATLAB 对数组操作进行了高度优化。你应该始终优先尝试使用向量化。
示例:对每个元素求平方
Section titled “示例:对每个元素求平方”假设你有一个数字数组,并想对每个数字求平方。
% 慢速的、基于循环的方法(如果可能请避免)input_array = [1, 2, 3, 4, 5];output_array = zeros(size(input_array)); % 预分配以提高性能for i = 1:length(input_array) output_array(i) = input_array(i)^2;end
% 快速的、向量化方法(最佳方法)input_array = [1, 2, 3, 4, 5];output_array_vectorized = input_array.^2; % .^ 运算符是逐元素幂运算
disp(output_array_vectorized);向量化版本更简洁、更精炼,并且显著更快,特别是对于大型数组。输出为:
1 4 9 16 25对数值数组使用 arrayfun(必要时)
Section titled “对数值数组使用 arrayfun(必要时)”当你想应用的函数无法轻易向量化时,你应该使用 arrayfun。arrayfun 将函数应用于数组的每个元素,但它通常只是 for 循环的一种更简洁的语法,并且不提供与真正向量化相同的性能优势。
B = arrayfun(func, A)B: 输出数组。func: 你想要应用的函数的句柄。这通常是用@创建的匿名函数。A: 输入数组。
示例:应用自定义的、非向量化函数
Section titled “示例:应用自定义的、非向量化函数”想象你有一个复杂的自定义函数,它只对标量输入操作。
% 让我们定义一个非向量化的自定义函数my_complex_func = @(x) sin(x) + x^2 - log(x);
% 数字数组input_array = [1, 2, 3, 4, 5];
% 使用 arrayfun 将函数应用于每个元素output_array = arrayfun(my_complex_func, input_array);
disp(output_array);虽然这可行,但一个更好的长期解决方案是重写 my_complex_func 以使其向量化:
% 函数的向量化版本my_vectorized_func = @(x) sin(x) + x.^2 - log(x);output_better = my_vectorized_func(input_array); % 这更快!对元胞数组使用 cellfun
Section titled “对元胞数组使用 cellfun”元胞数组的每个单元格可以包含不同类型和大小的数据,因此无法进行向量化。对于这些情况,cellfun 是适当的工具。
B = cellfun(func, C)示例 1:获取每个字符串的长度
Section titled “示例 1:获取每个字符串的长度”在现代 MATLAB 中,你应该使用 string 数组来处理文本。但如果你有一个遗留的字符向量 cell 数组,那么 cellfun 是完美的。
% 创建一个字符向量元胞数组input_cell_array = {'apple', 'banana', 'cherry'};
% 使用 cellfun 对每个元素应用 length 函数% 注意:在现代 MATLAB 中,更推荐对字符串数组使用 strlength()lengths = cellfun(@length, input_cell_array);
disp(lengths);结果是长度数组:
5 6 6示例 2:求单元格中每个数值数组的和
Section titled “示例 2:求单元格中每个数值数组的和”如果每个单元格包含不同大小的数值数组,cellfun 可以处理它们。
% 创建一个数值数组的元胞数组numeric_cells = {[1, 2, 3], [4, 5], [6, 7, 8, 9]};
% 定义一个函数句柄来计算和sum_function = @(arr) sum(arr);
% 使用 cellfun 应用求和函数output_sums = cellfun(sum_function, numeric_cells);
disp(output_sums);结果是每个单元格内容的和:
6 9 30性能与最佳实践总结
Section titled “性能与最佳实践总结”- 优先向量化:始终尝试使用逐元素运算符(
.*、./、.^)和向量化函数(sin、log、sum等),以获得最佳性能和可读性。 - 谨慎使用
arrayfun:仅当函数无法向量化时,才将arrayfun用于数值数组。 - 对元胞数组使用
cellfun:这是处理元胞数组异构内容的预期且高效的方法。 'UniformOutput', false:如果你通过cellfun或arrayfun应用的函数返回不同类型或大小的值,则必须指定此名称-值对。结果将是一个元胞数组。示例:sizes = cellfun(@size, numeric_cells, 'UniformOutput', false);