MATLAB R2019aでsubstrが見つかりません。原因はなんでしょうか?
10 views (last 30 days)
Show older comments
MATLAB R2019a でsubstrが見つかりません。原因はなんでしょうか?
ドキュメンテーションを確認したところ、R2018bから導入されているらしいのですが、コマンドを叩いても表示されず困っています。
0 Comments
Answers (2)
Tomotaka Hirata
on 14 Aug 2020
Edited: Tomotaka Hirata
on 14 Aug 2020
僕の場合は自分で作りました。
substr = (@(s_or_c, i, n)feval(@(c, i, n) c(i:(i+n-1)),feval(@(s_or_c) char(s_or_c),s_or_c),i,n));
これをコマンドラインにコピペすれば、substrを書き換えたりclear substrしたりしない限り、substrが利用可能になります。
substr("hello world", 2, 6)
と打てば「'ello w'」が返ります。
以下、解説
入力cが文字ベクトル(1重引用符で括られたもの)のとき、
「無名関数」というのを利用して定義すればいいです。
substr = @(c,i,n) c(i:(i+n-1));
とすることで、substrが実現します。
無名関数
@(x, ..) 関数や演算子など(x, ..);
は、
function rtn = anonymous(x, ..)
rtn = 関数や演算子など(x, ..)
end
のようなanonymous.mが「あるとみなして」anonymous(x, ...)を返してくれという命令です。
つまり、先ほどのコードでは、
function rtn = anonymous(c, i, n)
rtn = c(i:(i+n-1));
end
がある
とみなして、
substr = anonymous(c,i,n);
をやったのと同じです。
例えば
substr('hello world', 2, 6)
は'ello w'を返却します。
しかし、ここにはまだ問題が残っています。
substr("hello world", 2, 6)
は機能しないのです。
2重引用符で括られたものは「文字列」であり、文字ベクトルとは別物だからです。
文字列は、char(文字列)のようにすることで文字ベクトルに変換できます。
(蛇足: ちなみにchar(文字ベクトル)は、そっくりそのまま文字ベクトルを返します)
したがって、
substr(char("hello world"), 2, 6)
ならOKです。
ただ、これではダサいですよね。
substr("hello world", 2, 6)
でもちゃんと動くようにしましょう。
substr = @(str,i,n) char(str)(i:(i+n-1));
ならいいでしょうか?
いいえ。
matlabでは、括弧が隣り合うと、エラーになります。
したがって、
substr = @(str,i,n) (c = char(str); c(i:(i+n-1)));
でいけそうです。
しかしこれもダメです。無名関数は文を1つしか持たせられないからです。
何とかして無名関数で書きたい場合、
「feval関数」というのを何度も用いることで書けます。
fevalは、次のような関数です。
「feval(@f, x) が f(x) を返却する」
「feval(@g, x, y)が g(x, y)を返却する」
・・・
例1:
feval(@cos, 3.14)
は、cos(3.14)つまり-1を返却します。
例2:
feval(@mod, 10,3)
は、mod(10,3)つまり1 を返却します。
また、
feval関数の第1引数には無名関数も持ってこれます。
例3:
feval(@(c,i,n) c(i:(i+n-1)), 'hello_world', 2, 6)
は、substr('hello world', 2, 6)つまり'ello w'を返します。
ややこしいですが、
「'無名関数'内でfevalを利用し、
そのfeval内で'無名関数'を利用し、
その'無名関数'内でfevalを利用し
そのfeval内で'無名関数'を利用し、
その'無名関数'内でfevalを利用し
そのfeval内で...」
のようなことを繰り返すと、複数の文を無名関数で実行できます。
(理由は、「複数の文」全体を、一つの文としてみることが可能になるからです)
いきなり例を示すと混乱するので(もし皆さんが混乱しないとしても、説明している僕のほうが混乱します笑)、
どんな無名関数をつかうか、先に決めましょう。
関数その1: (s_or_c) → c
引数:
s_or_c: 文字列かもしれないし文字ベクトルかもしれないもの。
戻り値:
c: 確実に文字ベクトル
内容(分かりやすい表現):
c = char(s_or_c);
内容(無名関数の書き方で)
@(s_or_c) char(s_or_c);
関数その2: (c, i, n) → answer
引数:
c
i
n
戻り値:
answer: 得たい部分文字列
内容(分かりやすい表現):
answer = c(i:(i+n-1));
内容(無名関数の書き方で)
@(c, i, n) c(i:(i+n-1));
では、これを書いてみましょう。
substr = ...
(...
@(s_or_c, i, n) ...
feval ... %◆
... %関数その2を無名で定義し、利用します。 %◆
(... %◆
@(c, i, n) c(i:(i+n-1)), ... %◆
... %関数その2を定義 %◆
... %◆
feval ... %★ %◆
... %関数その1を無名で定義し、利用します。%★ %◆
(... %★ %◆
@(s_or_c) char(s_or_c), ... %★ %◆
... %関数その1を定義 %★ %◆
... %★ %◆
s_or_c ... %★ %◆
... %関数その1を利用 %★ %◆
), ... %★ %◆
... %★全体がcとして評価される(=あたかもcであるかのように振る舞う) %◆
i, n ... %(★=c)と繋げて読むと、c,i,nとなっている。 %◆
... %関数その2を利用 %◆
)... %◆
... %◆全体がanswerとして評価される
);
こんな感じです。
それでは、失礼いたします。
0 Comments
See Also
Categories
Find more on 命名規則 in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!