web-dev-qa-db-ja.com

最初にローカル変数に割り当てることなく、関数によって返されたMATLAB配列にインデックスを付けるにはどうすればよいですか?

たとえば、magic(5)から中央の値を読み取りたい場合、次のようにできます。

M = magic(5);
value = M(3,3);

value == 13を取得します。次のいずれかのようなことができるようにしたいと思います。

value = magic(5)(3,3);
value = (magic(5))(3,3);

中間変数を不要にします。ただし、MATLABはUnbalanced or unexpected parenthesis or bracketの前の最初の括弧で3について文句を言います。

最初に変数に割り当てることなく、配列/行列から値を読み取ることは可能ですか?

338
Joe Kearney

実際にはis必要なことを行うことができますが、インデックス演算子の関数形式を使用する必要があります。 ()を使用してインデックス作成操作を実行すると、実際には subsref 関数を呼び出しています。だから、あなたはできませんがこれを行う:

value = magic(5)(3, 3);

あなたはcanこれを行うことができます:

value = subsref(magic(5), struct('type', '()', 'subs', {{3, 3}}));

Glyいですが、可能です。 ;)

一般に、インデックス付けステップを関数呼び出しに変更するだけで、2セットの括弧が連続して続くことはありません。これを行う別の方法は、独自の 匿名関数 を定義して、添え字付きのインデックス付けを行うことです。例えば:

subindex = @(A, r, c) A(r, c);     % An anonymous function for 2-D indexing
value = subindex(magic(5), 3, 3);  % Use the function to index the matrix

しかし、すべてを言って完了したら、一時的なローカル変数ソリューションはmuchより読みやすく、間違いなく私が提案するものです。

367
gnovice

良いブログ投稿 on Matlabのアートのローレン 数日前に役立つかもしれない宝石がいくつかありました。特に、次のようなヘルパー関数を使用します。

paren = @(x, varargin) x(varargin{:});
curly = @(x, varargin) x{varargin{:}};

paren()は次のように使用できます

paren(magic(5), 3, 3);

戻ります

ans = 16

また、これはgnoviceの答えよりも高速になると推測しますが、チェックしていません(プロファイラーを使用してください!!!)。そうは言っても、これらの関数定義をどこかに含める必要があります。私は個人的にそれらを独立した機能にしました。なぜなら、それらは非常に便利だからです。

これらの関数およびその他の関数は、MATLABアドオンエクスプローラーまたは ファイル交換 で利用可能なFunctional Programming Constructsアドオンで利用可能になりました。

126
T. Furfaro

文書化されていない機能の使用についてどう思いますか?

>> builtin('_paren', magic(5), 3, 3)               %# M(3,3)
ans =
    13

またはセル配列の場合:

>> builtin('_brace', num2cell(magic(5)), 3, 3)     %# C{3,3}
ans =
    13

魔法のように:)


更新:

悪いニュース、上記のハックはR2015bではもう機能しません!それは問題ありません、文書化されていない機能であり、サポートされている機能として信頼することはできません:)

このタイプのものはどこにあるのか疑問に思う人は、fullfile(matlabroot,'bin','registry')フォルダーを見てください。そこには、あらゆる種類の便利なものをリストしたXMLファイルがたくさんあります。これらの関数の一部を直接呼び出すと、MATLABセッションが簡単にクラッシュする可能性があることに注意してください。

75
Amro

少なくともMATLAB 2013aでは、 getfield を次のように使用できます。

a=Rand(5);
getfield(a,{1,2}) % etc

(1,2)の要素を取得するには

52
Ian M. García

残念ながら、magic(5)(3,3)のような構文はmatlabではサポートされていません。一時的な中間変数を使用する必要があります。使用後にメモリを解放できます。

tmp = magic(3);
myVar = tmp(3,3);
clear tmp
15
second

実行時間を標準の方法(結果を割り当ててからエントリにアクセスする)と比較する場合、それらはまったく同じであることに注意してください。

subs=@(M,i,j) M(i,j);
>> for nit=1:10;tic;subs(magic(100),1:10,1:10);tlap(nit)=toc;end;mean(tlap)

ans =

0.0103

>> for nit=1:10,tic;M=magic(100); M(1:10,1:10);tlap(nit)=toc;end;mean(tlap)

ans =

0.0101

私の意見では、一番下の行は次のとおりです。MATLABにはポインターがありません。

12
titus

新しい関数を作成すると、より簡単になります。

function [ element ] = getElem( matrix, index1, index2 )
    element = matrix(index1, index2);
end

そしてそれを使用します:

value = getElem(magic(5), 3, 3);
6
Vugar

これを行うには、最初の表記が最も簡潔な方法です。

M = magic(5);  %create
value = M(3,3);  % extract useful data
clear M;  %free memory

これをループで実行している場合は、毎回Mを再割り当てするだけで、clearステートメントも無視できます。

4
Andreas GS

Amroの答えを補完するために、fevalの代わりにbuiltinを使用できます。演算子関数をオーバーロードしようとしない限り、実際には違いはありません。

BUILTIN(...)はFEVAL(...)と同じですが、オーバーロードされた関数が存在する場合でも元の組み込みバージョンの関数を呼び出します(これが機能するには、BUILTINをオーバーロードしてはいけません)。

>> feval('_paren', magic(5), 3, 3)               % M(3,3)
ans =
    13

>> feval('_brace', num2cell(magic(5)), 3, 3)     % C{3,3}
ans =
    13

おもしろいのは、fevalbuiltinよりもわずかに速い(〜3.5%)ように見えることです。少なくともMatlab 2013bでは、fevalとは異なり、builtinは関数がオーバーロードされているかどうかを確認する必要があるため、奇妙です:

>> tic; for i=1:1e6, feval('_paren', magic(5), 3, 3); end; toc;
Elapsed time is 49.904117 seconds.
>> tic; for i=1:1e6, builtin('_paren', magic(5), 3, 3); end; toc;
Elapsed time is 51.485339 seconds.
1
nirvana-msu