cellfun関数を使用すると、セル配列に格納されているすべての値に対して同じ関数を適用させることができることを解説しました。
また、ちょっとした処理を定義する場合には無名関数というものが存在するということを以下で解説しました。
このcellfun関数と無名関数ですが、組み合わせると様々な処理をループ処理なしに実装することができ、非常に便利です。
ここでは無名関数とcellfun関数の組み合わせについて実例交えて解説していきたいと思います。
cellfun関数で無名関数を呼び出すシチュエーション
cellfun関数で無名関数を呼び出すシチュエーションですが、大きく以下の2つのシチュエーションが考えられます。
①行いたい処理が1行で書くことができ、わざわざ新たな関数を起こすまでもない場合
②関数の引数が複数あり、そのうち一部の引数については固定の値としたい場合
行いたい処理が1行で書くことができ、わざわざ新たな関数を起こすまでもない場合
文字列の先頭2文字だけ取り出すことを考えます。まず、文字列’sample’が格納された変数strの文字列の先頭2文字を取り出す処理は
str(1 : 2);
と、1行で表すことができます。
これを無名関数にして、1つの変数からだけでなく、セル配列に格納されているすべての文字列に対して同じことを行いたいと思います。
例えば以下のように文字列がセル配列に格納されているとします。
inputCell = {'one', 'two', 'three', 'four'};
このセル配列に格納されている文字列から先頭2文字だけ抜き出すには
retCell = cellfun(@(x) x(1 : 2), inputCell, 'UniformOutput', false);
と記載することができます。
実際に実行した結果は以下の通りです。
ループ処理を使うことなく僅か1行の処理で行うことができました。
このように1行で済むような処理をセル配列の全部に適用したい場合、無名関数とcellfun関数の組み合わせで実現することができます。
関数の引数が複数あり、そのうち一部の引数については固定の値としたい場合
cellfun関数の基本的な使い方は以下の通りです。
cellfun(@関数名, セル配列);
しかし引数が複数あり、片方はセル配列の値全て入れたいけど、もう片方はそうしたくない場合もあります。
例えば、指定した文字列がある文字数以上であれば文字列’Yes’を、文字数未満であれば文字列’No’を返す関数checklenを以下のように作成したとします。
function ret = checklen(str, len)
if length(str) >= len
ret = 'Yes';
else
ret = 'No';
end
この関数を用いて、文字列が格納されたセル配列inputCellの各文字列に対して、4文字以上であれば文字列’Yes’を3文字未満であれば’No’を得たい場合を考えます。
この場合、関数の1つ目の引数はセル配列を渡しますが、もう一つは’4’という固定の数字としたいので、単純にcellfun関数を使用して渡すことができません。
このような場合、以下のよう無名関数を使用することでやりたいことが実現できます。
retStr = cellfun(@(x) checklen(x, 4), inputCell, 'UniformOutput', false);
実施した結果は以下の通りです。
やりたいことが実現できていることが確認できます。
とりあえず、関数の一部引数だけをセル配列で渡す場合は無名関数を使ういうことを覚えておけばよいかと思います。
cellfun関数を使用する際に気を付けること
少し本筋と離れる話なのですが。
cellfun関数と無名関数の組み合わせで色々できるので、ついつい無駄に活用してしまうことがあります。
しかし、MATLABは標準でセル配列を受け取ることができる関数も沢山存在するので、何でもかんでもcellfun関数を使う必要はありません。
例えばセル配列array1に格納されている文字列が指定した文字列’abc’と一致しているかをチェックする場合を考えてみます。
文字列の等価性をチェックする関数としてstrcmp関数がありますが、strcmp関数は文字列だけでなくセル配列を指定することも可能です。
そのためcellfun関数を使用しなくても
ret = strcmp(array1, 'abc')
とするだけでやりたいチェックを行うことができます。
これをわざわざ
ret = cellfun(@(x) strcmp(x, 'abc'), array1)
とすると、処理が冗長となってしまい、処理時間もかなり遅くなってしまいます。
cellfun関数を使用する前に、まずはそもそも関数がセル配列を許容しているかどうかチェックしておく必要があります。
コメント