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は、論理配列、数値配列、文字列配列、構造体配列、またはセル配列にすることができます。A のarrayfunすべての要素を個別に関数fcnに渡し、結果を収集します。同等の擬似コードは次のとおりです。
cls = class (fcn (A(1)); B = zeros (size (A), cls); for i = 1:numel (A) B(i) = fcn (A(i)) endfor
指定された関数は、3 つ以上の入力引数を取ることもできます。その場合、入力引数は 3 番目の入力引数A2、4 番目の入力引数 A2、… のように指定されます。配列入力引数が 1 つ以上指定されている場合は、すべての入力引数のサイズが同じである必要があります。例:
arrayfun (@atan2, [1, 0], [0, 1])
⇒ [ 1.57080 0.00000 ]
追加の文字列入力引数の後の パラメータval が"UniformOutput"設定されている場合true(デフォルト)、指定された関数fcn は単一の要素を返す必要があり、その要素は戻り値に連結され、行列型になります。それ以外の場合、そのパラメータが に設定されている場合、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はfcnがエラーを生成した場合に呼び出す関数を定義します。関数の定義は次の形式でなければなりません。
function [...] = errfcn (s, ...)
ここで、 sによって指定される、fcnに関連する errfcnへの追加の入力引数があります。これは、要素 、 、 を持つ構造体で、それぞれエラー識別子、エラー メッセージ、およびエラーの原因となった配列要素のインデックスを示します。 errfcnの出力引数のサイズは、 fcnの出力引数と同じサイズである必要があります。そうでない場合は、実際のエラーがスローされます。例:
"identifier""message""index"
function y = ferr (s, x), y = "MyString"; endfunction
arrayfun (@str2num, [1234],
"UniformOutput", false, "ErrorHandler", @ferr)
⇒
{
[1,1] = MyString
}
See also: spfun, cellfun, structfun.
: y = spfun (f, S)
Sの非ゼロ要素を計算します。 f (S)
入力関数fは、通常はスパースである入力行列Sの非ゼロ要素にのみ適用されます。関数f は、文字列、関数ハンドル、またはインライン関数として渡すことができます。
出力y は、入力Sと同じスパース構造を持つスパース行列です。 は、のときに関数fをスパース行列 Sspfunに単純に適用する場合とは異なり、スパース構造を保存します。 f (0) != 0
スパース性保存spfunと通常の関数適用 S = pi * speye (2,2) S =
圧縮列スパース (行 = 2、列 = 2、nnz = 2 [50%]) (1, 1) -> 3.1416 (2, 2) -> 3.1416 y = spfun (@cos, S) y =
C圧縮列スパース (行 = 2、列 = 2、nnz = 2 [50%]) (1, 1) -> -1 (2, 2) -> -1 y = cos (S) y =
圧縮列スパース (行 = 2、列 = 2、nnz = 4 [100%]) (1, 1) -> -1 (2, 1) -> 1 (1, 2) -> 1 (2, 2) -> -1
See also: 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)
セル配列Cの要素に対して 「 fcn 」という名前の関数を評価します。
Cの要素は、名前付き関数に個別に渡されます。関数fcnは、関数の1つです。
isempty 空の要素の場合は 1 を返します。
islogical 論理要素の場合は 1 を返します。
isnumeric 数値要素の場合は 1 を返します。
isreal 実数要素の場合は 1 を返します。
length セル要素の長さのベクトルを返します。
ndims 各要素の次元数を返します。
numel prodofsize 各セル要素内に含まれる要素の数を返します。この数は、各セル要素のオブジェクトの寸法の積です。
size k番目の次元に沿ったサイズを返します。
isclass クラスの要素に対して 1 を返します。
numel prodofsize 各セル要素内に含まれる要素の数を返します。この数は、各セル要素のオブジェクトの寸法の積です。
size k番目の次元に沿ったサイズを返します。
isclass クラスの要素に対して 1 を返します。
さらに、インライン関数、関数ハンドル、または関数名(文字列)の形式でcellfun任意の関数fcnを受け入れます。関数は 1 つ以上の引数を取ることができ、入力引数はC1、C2などで指定されます。例:
cellfun ("atan2", {1, 0}, {0, 1})
⇒ [ 1.57080 0.00000 ]
Tの出力引数の数はcellfun関数の出力引数の数と一致し、1 より大きくなる場合があります。関数の出力が複数ある場合、それらは 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 (デフォルト) に設定されている場合、関数はスカラーを返す必要があり、それらは戻り配列に連結されます。 が"UniformOutput"false の場合、出力はセル配列に連結されます。 例:
cellfun ("lower", {"Foo", "Bar", "FooBar"},
"UniformOutput", false)
⇒ {"foo", "bar", "foobar"}
パラメータ が与えられると"ErrorHandler"、errfcn はfcn がエラーを生成した場合に呼び出される関数を定義します。関数の形式は次のとおりです。
function [...] = errfcn (s, ...)
ここで、 sによって指定される、fcnに関連する errfcnへの追加の入力引数があります。これは 、、、および要素を持つ構造体で、それぞれエラー識別子、エラー メッセージ、およびエラーの原因となった要素の入力引数へのインデックスを示します。例: "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
See also: arrayfun, structfun, spfun.
: A = structfun (fcn, S) : A = structfun (…, "ErrorHandler", errfcn) : A = structfun (…, "UniformOutput", val) : [A, B, …] = structfun (…)
構造体Sのフィールドに対して nameという名前の関数を評価します。 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
パラメータerrfcn"ErrorHandler"が与えられると、fcn がエラーを生成した場合に呼び出される関数が定義されます。関数の形式は次のとおりです。
function [...] = errfcn (se, ...)
ここで、 errfcnにはfcnに関連する 追加の入力引数があり、se"identifier"で与えられます。これは、要素 、 、 を持つ構造体で、"message"それぞれ"index"エラー識別子、エラー メッセージ、エラーの原因となった要素の入力引数のインデックスを示します。エラー ハンドラの使用方法の例については、 を参照してくださいcellfun。
See also: cellfun, arrayfun, spfun.
以前のアドバイスと同様に、最高のパフォーマンスを得るためには、可能な限り Octave の組み込み関数を使用するようにしてください。このアドバイスは、上記の 4 つの関数に特に当てはまります。たとえば、2 つの配列を要素ごとに加算する場合、組み込みの加算関数へのハンドルを使用する @plusか、匿名関数を定義することができます@(x,y) x + y。ただし、匿名関数は最初の方法よりも 60% 遅くなります。匿名関数の代わりに使用できる基本的な関数のリストについては、 「演算子のオーバーロード」を参照してください。