MATLABスクリプトを作成するにあたり、個人的に是非とも知っておきたい関数として挙げたいのがcellfun関数です。
Cなどの言語では配列のそれぞれの要素に対して処理を実行するにはfor文等でループさせて配列の中身を一つ一つ取り出して処理を行う必要があります。
しかしcellfun関数を使用するとループさせることなく配列の要素全てに対して一気に処理を実行することができます。
そのため、使いこなすことでコードのスリム化や処理速度のアップなどのメリットが見込めます。
また、他の言語では見ないような文法なのでMATLAB初心者の方がソースコードを読んだときに詰まってしまうポイントでもあるかと思います。
ここでは、cellfun関数とはどんなものか、基本的なことを解説したいと思います。
cellfun関数とほぼ同じ機能を持つarrayfun関数というものも存在します。
処理を適用したい値がセル配列に入っていればcellfun関数、通常の配列に入っていればarrayfun関数を使用します。
使い方は全く一緒なのでここに記載されていることは全てarrayfun関数にも適用されます。
その他にも構造体のメンバーを渡すstructfun関数やスパース行列を渡すspfun関数がありますが、この2つ、僕は今のところ使用したこと無いので一旦置いておいても良いかと思います。。。
cellfun関数の基本的な使い方
cellfun関数の基本構文は以下の通りです。
cellfun(@関数名, セル配列)
第一引数に関数名、第二引数に渡したいセル配列を指定します。
関数名を指定する際、先頭に”@”を付与することがポイントです。
例として値が空かどうかをチェックする関数isempty関数をセル配列の各要素に対して適用させてみます。
まずチェックするセル配列として以下のセル配列を準備します。
sampleCell = {'a', 'b', 'c', '', 'd', ''}
このセル配列の各要素が空かどうかチェックします。
ret = cellfun(@isempty, sampleCell)
実行すると以下のようにセル配列の各要素に対してisempty関数を実行した結果が返ってきます。
UnifomOutputオプションについて
cellfun関数は’UnifomOutput’というオプションがあり、デフォルトではこのオプションが’true’となっています。
このオプションに’false’を指定すると戻り値が配列ではなくセル配列となります。
関数の戻り値がスカラー値でない場合、例えば文字列が返ってくるような場合や、配列が返ってくる場合、通常の配列には格納することができません。
そのため、’UnifomOutput’オプションをfalse指定して戻り値をセル配列に格納する必要があります。
cellfun関数で自作の関数を呼び出す
セル配列で実行する関数はMATLAB標準の関数だけでなく、自作の関数も呼び出せます。
例として、引数として渡した文字列を4文字以上であれば文字列’Yes’を、3文字以下であれば文字列’No’を返す関数myfunを以下のように定義します。
function ret = myfun(str)
if length(str) >= 4
ret = 'Yes';
else
ret = 'No';
end
また、チェックしたい文字列が格納されたセル配列を以下のように定義します。
inputCell = {'one', 'two', 'three', 'four', 'five'};
作成したセル配列inputCellの各要素に対して自作したmyfunを適用します。
ret = cellfun(@myfun, inputCell, 'UniformOutput', false);
先ほどの段で説明したようにこの関数の戻り値は文字列なので通常の配列には格納できません。
そのため’UniformOutput’オプションをfalse指定して戻り値をセル配列に格納しています。
複数の配列を渡す
複数の引数を必要とする関数に対してもcellfun関数を使用することができます。
cellfun関数を使用して3つの引数を受け取る関数を実行するには以下のように記載します。
cellfun(@関数名, セル配列1, セル配列2, セル配列3)
‘UniformOutput’オプションをfalseにすることももちろん可能です。その場合は以下のように記載します。
cellfun(@関数名, セル配列1, セル配列2, セル配列3, 'UniformOutput', false)
関数は各セル配列の同じ行に格納されている値の組み合わせが引数として渡されます。
イメージとしては以下の通りです。
例として、引数として渡した2つの文字列が共に4文字以上であれば文字列’Yes’を、どちらか片方でも3文字以下であれば文字列’No’を返す関数myfun2を以下のように定義します。
function ret = myfun(str1, str2)
if length(str1) >= 4 && length(str2) >= 4
ret = 'Yes';
else
ret = 'No';
end
チェックしたい文字列が格納されたセル配列を以下のように定義します。
inputCell1 = {'one', 'two', 'three', 'four', 'five'};
inputCell2 = {'six', 'seven', 'eight', 'nine', 'ten'};
cellfun関数を用いてmyfun2関数を実行します。
ret = cellfun(@myfun2, inputCell1, inputCell2, 'UniformOutput', false);
実行すると以下のような結果が返ってきます。
戻り値retの1番目にはmyfun2関数に文字列’one’と’six’を渡した結果として’No’、
戻り値retの2番目にはmyfun2関数に文字列’two’と’seven’を渡した結果として’No’、
戻り値retの3番目にはmyfun2関数に文字列’three’と’eight’を渡した結果として’Yes’、
戻り値retの4番目にはmyfun2関数に文字列’four’と’nine’を渡した結果として’Yes’、
戻り値retの5番目にはmyfun2関数に文字列’five’と’ten’を渡した結果の’No’
が格納されていることが確認できます。
コメント