19.3函数应用

一般来说,函数应该已经考虑到矩阵参数,并且应该以系数化的方式考虑整个矩阵运算。有时,因为各种原因,以这种方式写作似乎很困难或不可能。对于这些情况,Octave提供了将函数应用于数组、数组或结构体的每个元素的函数。

 
: B = arrayfun (fcn, A)
: B = arrayfun (fcn, A1, A2, …)
: [B1, B2, …] = arrayfun (fcn, A, …)
: B = arrayfun (…, "UniformOutput", val)
: B = arrayfun (…, "ErrorHandler", errfcn)

对数组的每个元素执行一个函数。

这对于不接受数组参数的函数非常有用。如果函数确实接受数组参数,则为较好的直接调用函数。

第一个输入参数fcn可以是字符串、函数句柄、线性函数或匿名函数。输入参数A可以是逻辑数组、数字数组、字符串数组、结构体数组或元胞数组。arrayfun传递的所有元素A单独到函数fcn并收集结果。等效的伪代码是

cls = class (fcn (A(1));
B = zeros (size (A), cls);
for i = 1:numel (A)
  B(i) = fcn (A(i))
endfor

命名函数还可以接受两个以上的输入参数,其中inputarguments作为第三个输入参数A2,第四个输入自变量A2,…如果给定多个数组输入参数,则所有输入参数的大小必须相同。例如

arrayfun (@atan2, [1, 0], [0, 1])
     ⇒ [ 1.57080   0.00000 ]

如果参数val在另一个字符串输入参数之后"UniformOutput"已设置true(默认值),然后命名函数fcn必须返回一个元素,然后将该元素连接到返回值,并且该元素的类型为matrix。否则,如果该参数设置为false,然后将输出连接到元胞数组中。例如:

arrayfun (@(x,y) x:y, "abc", "def", "UniformOutput", false)
⇒
   {
     [1,1] = abcd
     [1,2] = bcde
     [1,3] = cdef
   }

如果给定了多个输出参数,则命名函数必须返回预期的返回值数量,例如:

[A, B, C] = arrayfun (@find, [10; 0], "UniformOutput", false)
⇒
A =
{
   [1,1] =  1
   [2,1] = [](0x0)
}
B =
{
   [1,1] =  1
   [2,1] = [](0x0)
}
C =
{
   [1,1] =  10
   [2,1] = [](0x0)
}

如果参数errfcn在另一个字符串输入参数之后"ErrorHandler"是另一个字符串、函数句柄、内联函数或匿名函数,则errfcn在以下情况下定义函数tocallfcn生成错误。函数的定义必须为

function [...] = errfcn (s, ...)

其中有一个附加的输入参数errfcn相对于fcn,从给定s。这是一个包含元素的结构体"identifier", "message""index"分别给出导致错误的数组元素的错误标识符、错误消息和索引。的输出参数的大小errfcn的输出参数必须具有相同的大小fcn,否则将引发真正的错误。例如

function y = ferr (s, x), y = "MyString"; endfunction
arrayfun (@str2num, [1234],
          "UniformOutput", false, "ErrorHandler", @ferr)
⇒
   {
     [1,1] = MyString
   }

详见: spfun, cellfun, structfun.

广告
 
: y = spfun (f, S)

计算f (S)的非零元素S.

输入函数f仅应用于输入矩阵的非零元素S其通常是稀疏的。函数f可以作为字符串、函数句柄或内联函数传递。

输出y是与输入具有相同稀疏性结构体的稀疏矩阵S. spfun保留稀疏性结构体,该结构体不同于简单地应用函数f到稀疏矩阵Sf (0) != 0.

用例

稀疏性保留spfun与正常函数应用程序相比

S = pi * speye (2,2)
S =

Compressed Column Sparse (rows = 2, cols = 2, nnz = 2 [50%])

  (1, 1) -> 3.1416
  (2, 2) -> 3.1416

y = spfun (@cos, S)
y =

Compressed Column Sparse (rows = 2, cols = 2, nnz = 2 [50%])

  (1, 1) -> -1
  (2, 2) -> -1

y = cos (S)
y =

Compressed Column Sparse (rows = 2, cols = 2, nnz = 4 [100%])

  (1, 1) -> -1
  (2, 1) -> 1
  (1, 2) -> 1
  (2, 2) -> -1

详见: arrayfun, cellfun, structfun.

广告
 
: A = cellfun ("fcn", C)
: A = cellfun ("size", C, k)
: A = cellfun ("isclass", C, class)
: A = cellfun (@fcn, C)
: A = cellfun (fcn, C)
: A = cellfun (fcn, C1, C2, …)
: [A1, A2, …] = cellfun (…)
: A = cellfun (…, "ErrorHandler", errfcn)
: A = cellfun (…, "UniformOutput", val)

评估名为“”的函数fcn在元胞数组的元素上C.

中的元素C分别传递给命名函数。The functionfcn可以是函数之一

isempty

对于空元素,返回1。

广告
islogical

逻辑元素返回1。

广告
isnumeric

对于数字元素,返回1。

广告
isreal

对于实际元素,返回1。

广告
length

返回数组元素长度的向量。

广告
ndims

返回每个元素的维度数。

广告
numel
prodofsize

返回每个数组元素中包含的元素数。数字是对象在每个单元元素处的尺寸的乘积。

广告
size

沿返回大小k-th维度。

广告
isclass

的元素返回1class.

广告

此外,cellfun接受任意函数fcn以内联函数、函数句柄或函数名称的形式(在一个字符字符串中)。函数可以接受一个或多个参数,输入参数从C1, C2等。例如:

cellfun ("atan2", {1, 0}, {0, 1})
     ⇒ [ 1.57080   0.00000 ]

的输出参数数cellfun匹配函数的outputarguments的数量,并且可以大于一。当函数有多个输出时,它们将被收集到的输出参数中cellfun这样地:

function [a, b] = twoouts (x)
  a = x;
  b = x*x;
endfunction
[aa, bb] = cellfun (@twoouts, {1, 2, 3})
     ⇒
        aa =
           1 2 3
        bb =
           1 4 9

请注意,默认情况下,输出参数是与输入参数大小相同的数组。奇异(1x1)数组的输入自变量将自动扩展到其他自变量的大小。

如果参数"UniformOutput"如果设置为true(默认值),则函数必须返回标量,标量将连接到returnarray中。如果"UniformOutput"如果为false,则输出连接到一个(或多个)元胞数组。例如

cellfun ("lower", {"Foo", "Bar", "FooBar"},
         "UniformOutput", false)
⇒ {"foo", "bar", "foobar"}

给定参数"ErrorHandler"然后errfcn定义一个函数以在case中调用fcn生成错误。函数的形式是

function [...] = errfcn (s, ...)

其中有一个额外的输入参数errfcn相对于fcn,从给定s。这是一个包含元素的结构体"identifier", "message""index"将错误标识符、错误消息和索引分别提供给导致错误的元素的输入参数。例如

function y = foo (s, x), y = NaN; endfunction
cellfun ("factorial", {-1,2}, "ErrorHandler", @foo)
⇒ [NaN 2]

使用cellfun聪明地。这里的cellfun函数是避免循环的有用工具。它经常与匿名函数句柄一起使用;然而,调用匿名函数所涉及的开销与m文件函数的开销相当。将句柄传递给内置函数是错误的,因为解释器不参与内部循环。例如:

C = {...}
v = cellfun (@(x) det (x), C); # compute determinants
v = cellfun (@det, C);         # 40% faster

详见: arrayfun, structfun, spfun.

广告
 
: A = structfun (fcn, S)
: A = structfun (…, "ErrorHandler", errfcn)
: A = structfun (…, "UniformOutput", val)
: [A, B, …] = structfun (…)

评估名为的函数name关于结构体的字段S。的字段S传递给函数fcn个别地。

structfun接受任意函数fcn以线性函数、函数句柄或函数名称(在字符串中)的形式。如果是字符串参数,函数必须接受一个名为x,并且它必须返回一个字符串值。如果函数返回多个参数,它们将作为单独的返回变量返回。

如果参数"UniformOutput"如果设置为true(默认值),则函数必须返回一个元素,该元素将连接到返回值中。如果"UniformOutput"如果为false,则输出被放置到与输入结构体具有相同字段名的结构体中。

s.name1 = "John Smith";
s.name2 = "Jill Jones";
structfun (@(x) regexp (x, '(\w+)$', "matches"){1}, s,
           "UniformOutput", false)
  ⇒ scalar structure containing the fields:
       name1 = Smith
       name2 = Jones

给定参数"ErrorHandler", errfcn定义一个函数以在case中调用fcn生成错误。函数的形式是

function [...] = errfcn (se, ...)

其中有一个附加的输入参数errfcn相对于fcn,从给定se。这是一个包含元素的结构体"identifier", "message""index",分别给出导致错误的元素的输入自变量的错误标识符、错误消息和索引。有关如何使用错误处理程序的示例,详见cellfun.

详见: cellfun, arrayfun, spfun.

广告

与之前的建议一致,尽可能使用Octave内置函数以获得最佳性能。此建议尤其适用于上述四个函数。例如,当通过元素将两个数组添加在一起时,可以使用内置加法函数的句柄@plus或定义一个匿名函数@(x,y) x + y但是,该匿名函数比第一种方法慢60%。详见运算符重载,以获取可能用来代替匿名函数的基本函数列表。


版权所有 © 2024-2025 Octave中文网

ICP备案/许可证号:黑ICP备2024030411号-2