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


363

たとえば、中央の値をから読み取りたい場合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ます。

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


2
私はこのテーマについて次の記事も見つけました:mathworks.com/matlabcentral/newsreader/view_thread/280225誰かがこのテーマに関する新しい情報を持っています、それは実装されますか?

2
この構文は実際にはOctaveで正常に動作します。私がこの問題を発見したのは、MATLABを使用している同僚が私のコードの実行で問題を抱えていたときだけでした。
sffc 2015

2
一言で言えば、MATLAB。
user76284

1
再帰的抽出は、バージョン6以降のScilab(scilab.org)でも機能します。
StéphaneMottelet

testmatrix('magi', 5)(3, 3)Scilabの上とmagic(5)(3, 3)魔法のように両方の仕事オクターブ上!
Foad

回答:


384

実際にあなたが望むことをすること可能ですが、インデックス演算子の関数形式を使わなければなりません。を使用してインデックス付け操作を実行すると、()実際にはsubsref関数が呼び出されます。したがって、これを行うことはできませんが:

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

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

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

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

一般に、インデックス付けの手順を関数呼び出しに変更するだけで、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

ただし、すべてのことを言って実行すると、一時的なローカル変数のソリューションははるかに読みやすくなり、間違いなく私が提案することになります。


26
よく知っていますか!私はそれがかなり醜く、おそらくtemp-varソリューションよりも読みにくいことに同意します。目立たないあいまいなMATLAB知識の+1!
第二

57
それは嫌ですが、非常に明確な答えです。よくできました!それに戻る方法があると思ったはずです。temp変数を引き続き使用すると思います。
ジョー・カーニー

29
ただし、中間変数はまだ完全に作成されています。したがって、一時的なローカル変数を作成する必要がないことによってメモリを節約することが目的である場合、運はありません。
サムロバーツ

8
@SamRoberts:Matlabのような厳密な評価言語では、これを回避することはできません。人々がこれを望む主な理由は、簡潔さ/読みやすさであり、メモリの節約ではありません。
メカニカルカタツムリ

5
@SamRoberts:true、しかしそれclear一時的なものを呼び出す負担からあなたを救います(誰もこれをしません)-一時的なものはより長く
留まる

131

ちょうどあった優れたブログ記事ローレンは、MATLABの芸術にそれかもしれないのヘルプカップルの宝石で数日前。特に、次のようなヘルパー関数を使用します。

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

paren()ように使用できる場所

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

戻るだろう

ans = 16

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

これらの関数およびその他の関数は、MATLABアドオンエクスプローラーまたはファイル交換から利用できる関数型プログラミング構成アドオンで利用できるようになりました。


2
これは、ノービスの答えの後半の少し一般的なバージョンです。また良い。
ジョー・カーニー

どうmyfunc().attrですか?
gerrit 2013年

@ gerrit、atはどのように助けますか?また、x.attr()フィールドは、データベースツールボックスがない限り使用できません。
T.ファーファロ2013年

@ T.Furfaroハァッ?myfunc()属性を含む構造を返す場合、現在attrアクセスattrするには、私が行う必要がありますS = myfunc(); S.attr。問題はgetattr(myfunc(), 'attr')parencurlyヘルパーと同様に、ヘルパー機能を使用できるかどうかです。これがデータベースツールボックスとどう関係しているのか理解できません。
gerrit 2013年

2
@gerrit申し訳ありませんが、完全に混乱しています( "attr"が恣意的であることは知りませんでした。dbtbには、そのようなフィールドが明示的に定義されています)。あなたが探しているのはgetfield()
T. Furfaro

75

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

>> 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セッションが簡単にクラッシュする可能性があることに注意してください。


@RodyOldenhuis:私は今思い出せない、私はいくつかの埋め込みコードでそれを読んだに違いないと思う;)
Amro

2
':'エラーを回避するには、コロン(:)演算子をアポストロフィと共に使用する必要がありますUndefined function or variable "builtin"
ドミニク

@Dominikは:右、あなたが2番目の列をスライスしたいと言う、それは次のようになりますbuiltin('_paren', magic(5), ':', 2)(特定の場所では、として直接引用せずに作業を行う:とは対照的に、':'関数内から直接ではないpromptコマンドで実行しているときのように、私は推測します。それはパーサーのバグです!)
Amro、

2
endこれを使用する方法があると思いませんか?
knedlsepp 2015

2
@knedlsepp:いいえ、残念ながら、この構文ではend-trickery全体が機能しません。インデックス作成では明示的に指定する必要があります。(同じ制限が他のほとんどのリストされた回答に適用されます)
Amro

54

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

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

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


5
これは実際には素晴らしい方法です。欠点はありますか?
mmumboss 2014年

6
@mmumboss:これは文書化されていない動作であり、この機能は将来のバージョンで予告なしになくなる可能性があります。これに加えて、欠点はありません。
ダニエル

6
MATLAB2017b以降、この機能は文書化されています。
njspeer

15

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

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

12

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

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にはポインターがありません。それと共存する必要があります。


6

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

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

そしてそれを使います:

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

1
しかし、これはまさに何をするかsubrefです...しかし、より一般的な方法で。
シャイ

2
はい、より一般的な方法ですが、友好的ではありません...私の意見では非常に醜いです。
Vugar 2013年

4

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

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

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


6
これはより簡潔であり、あなたが言うように、ループ内でクリアすることは良い考えであることに同意しますが、問題は特に中間の割り当てを回避できるかどうかでした。
ジョー・カーニー

1

アムロの答えを補足するため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

面白いです何fevalほんの少し速くよりであるように思わbuiltinれる少なくともことを考えると奇妙であるのMatlab 2013b、中(3.5%〜によって)、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.

それは実際には奇妙なことではありません:MATLABは定義された関数のリストを保持しており、実行する検索はそれほど多くありません。feval「通常の」ことを行うため、このリストを最大限に活用できます。builtin他の場所を検索する必要があるため、組み込み関数のみを見つけます。このケースは「通常の」ケースほど最適化されていない可能性があります。なぜ、あまり頻繁に使用されないものを最適化するためにお金を使うのでしょうか。
クリスLuengo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.