10

i = [3 5]インデックスのリスト、例えば、ベクトルを与えましたv = 1:6。インデックスが与えられfたベクトルの論理マップを返す関数が必要です。例:vi

f(i, length(v)) = [0 0 1 0 1 0]

この関数を数百万回呼び出すので、できるだけ速くしたいと思います。このタスクを実行する組み込み関数はありますか?

4

7 に答える 7

10

ゲームに遅れていることはわかっていますが、と同じくらいエレガントな、より高速なソリューションを見つけたかったのismemberです。そして確かに、文書化されていないismembc機能を採用しているものがあります。

ismembc(v, i)

基準

N = 7;
i = [3 5];

%// slayton's solution
tic
for ii = 1:1e5
    clear idx;
    idx(N) = false;
    idx(i) = true;
end
toc

%// H.Muster's solution
tic
for ii = 1:1e5
    v = 1:N;
    idx = ismember(v, i);
end
toc

%// Jonas' solution
tic
for ii = 1:1e5
    idx = sparse(i, 1, true, N, 1);
end
toc

%// ismembc solution
tic
for ii = 1:1e5
    v = 1:N;
    idx = ismembc(v, i);
end
toc

これが私が得たものです:

Elapsed time is 1.482971 seconds.
Elapsed time is 6.369626 seconds.
Elapsed time is 2.039481 seconds.
Elapsed time is 0.776234 seconds.

驚くべきことに、ismembc確かに最速です!

編集:
の値が非常に大きい場合Nつまりvが大きい配列の場合)、より高速なソリューションは実際にはslayton(さらに言えばHebeleHododo)です。さまざまな戦略から選択できます。慎重に選んでください:)

H.Musterによる編集:
以下を含むベンチマーク結果があります_ismemberoneoutput

Slayton's solution:
   Elapsed time is 1.075650 seconds.
ismember:
   Elapsed time is 3.163412 seconds.
ismembc:
   Elapsed time is 0.390953 seconds.
_ismemberoneoutput:
   Elapsed time is 0.477098 seconds.

Index exceeds matrix dimensions.興味深いことに、エラーが発生したため、Jonasのソリューションは実行されません...

hoogamaphoneによる編集:両方の入力が数値、ソート済み、非スパース、非NaN値である必要があることに注意してください。これは、ソースドキュメントでは簡単に見落とされる可能性のある
詳細ですismembc

于 2013-01-30T15:35:25.000 に答える
5

使用できますismember

 i = [3 5];
 v = 1:6;

 ismember(v,i)

戻ります

ans =

     0     0     1     0     1     0

おそらくより高速なバージョンについては、試すことができます

builtin('_ismemberoneoutput', v, i)

あなたが指定したような行ベクトルに対してのみこれをテストしたことに注意してください。

于 2013-01-30T15:08:20.750 に答える
5

論理インデックスのベクトルを作成し、目的の位置を true/false に設定するだけです

idx = false( size( v) );
idx( i ) = true;

これは、次のように関数でラップできます。

function idx = getLogicalIdx(size, i)
  idx = false(size);
  idx(i) = true;
end

100 万回の操作ごとに同じサイズのインデックス ベクトルが必要な場合は、ベクトルを 1 回割り当ててから、反復ごとに操作します。

idx = false(size(v)); % allocate the vector
while( keepGoing)

  idx(i) = true; % set the desired values to true for this iteration

  doSomethingWithIndecies(idx);

  idx(i) = false; % set indices back to false for next iteration

end

本当にパフォーマンスが必要な場合は、mex 関数を記述してこれを行うことができます。これは、私が書いた非常に基本的なテストされていない関数で、他の方法よりも約 2 倍高速です。

#include <math.h>
#include <matrix.h>
#include <mex.h>

void mexFunction(int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[])
{
    double M;
    double *in;

    M = mxGetScalar(prhs[0]);
    in = mxGetPr(prhs[1]);
    size_t N = mxGetNumberOfElements(prhs[1]);



    plhs[0] = mxCreateLogicalMatrix( M,1 );
    mxLogical *out= mxGetLogicals( plhs[0] );


    int i, ind;
    for (i=0; i<N; i++){
        out[ (int)in[i] ] = 1;
    }

}

matlab でベクトルを割り当てる方法はいくつかあります。いくつかは他のものよりも高速です。適切な要約については、この文書化されていない Matlab の投稿を参照してください。

さまざまな方法を比較する簡単なベンチマークを次に示します。最後の方法は断然最速ですが、操作ごとに同じサイズの論理インデックス ベクトルを使用する必要があります。

N = 1000;
ITER = 1e5;

i = randi(5000,100,1);
sz = [N, 1];

fprintf('Create using false()\n');
tic;
for j = 1:ITER
    clear idx;
    idx = false( N, 1 );
    idx(i) = true;
end
toc;

fprintf('Create using indexing\n');
tic;
for j = 1:ITER
    clear idx;
    idx(N) = false;
    idx(i) = true;
end
toc;

fprintf('Create once, update as needed\n');
tic;
idx = false(N,1);
for j = 1:ITER
    idx(i) = true;
    idx(i) = false;
end
toc;

fprintf('Create using ismembc\n');
a = ones(N,1);
tic;
for j = 1:ITER

    idx = ismembc(1:N, i);
end
toc;
于 2013-01-30T14:58:48.983 に答える
2

idx 行列を使用して新しい変数をアドレス指定するだけで、ゼロが埋められます。

idx = [3 5];
a(idx) = true

末尾のゼロも必要でない限り、関数や長さを渡す必要はありません。

于 2013-01-30T15:03:12.430 に答える
2

@slayton のソリューションが最速だと思います。ただし、ベクトルが大きい場合、少なくともメモリを節約できるワンライナーの代替手段があります。

vecLen = 6;
logicalIdx = sparse(idx,1,true,vecLen,1);
于 2013-01-30T15:13:26.810 に答える
1

次のような関数を書くことができます:

function logicalIdx = getLogicalIdx(idx, v)
    logicalIdx = zeros(1,size(v,2));
    logicalIdx(idx) = 1;
end

関数を呼び出す場合:

v = 1:6;
idx = [3 5];
getLogicalIdx(idx,v)

出力は次のようになります。

ans =

     0     0     1     0     1     0
于 2013-01-30T15:00:22.620 に答える