2

私は2つの行列を持っていAますB. (Bのように連続している1:n)

Binの個々の行の出現箇所をすべて検索し、Aそれらの行インデックスを cell array に格納する必要がありますC。例については、以下を参照してください。

A = [3,4,5;1,3,5;1,4,3;4,2,1]
B = [1;2;3;4;5]

したがって、

C = {[2,3,4];[4];[1,2,3];[1,3,4];[1,2]}

私のアプリケーションでは、メモCはセル配列である必要はありません。Cの行ベクトルの長さが等しくないため、私はそれを提案するだけです。回避策を提案できる場合は、これも問題ありません。

の各行に対して ismember を実行するループを使用してみましたが、行列とが巨大で、約 100 万のエントリがあるB場合、これは遅すぎます。ベクトル化されたコードは高く評価されます。AB

(コンテキストを提供するために、これの目的は、メッシュで、単一の頂点に接続されている面を識別することです。私のデータは三角測量表現で「TR」の形式ではないため、関数 edgeattachments を使用できないことに注意してください。私が持っているのは、面のリストと頂点のリストだけです。)

4

2 に答える 2

1

について何の仮定もせずにそれを行うことができますBbsxfunとのこの使用法を試してくださいmat2cell:

M = squeeze(any(bsxfun(@eq,A,permute(B,[3 2 1])),2)); % 4x3x1 @eq 1x1x5 => 4x3x5
R = sum(M); % 4x5 -> 1x5
[ii,jj] = find(M);
C = mat2cell(ii,R)

上記のセルはC、例のように行ではなく列ベクトルになります。セルに行ベクトルを含めるには、C = mat2cell(ii',1,R)'代わりに を使用します。

私の唯一の懸念は、mat2cell何百万もの の値に対して遅くなる可能性があるRことですが、出力をセルに入れたい場合、どれだけうまくできるかわかりません。EDIT : Werner のループによる最初のソリューションのようにスパース行列を処理できる場合は、上記の最後の行を次のように置き換えます。

>> Cs = sparse(ii,jj,1)
Cs =
   (2,1)        1
   (3,1)        1
   (4,1)        1
   (4,2)        1
   (1,3)        1
   (2,3)        1
   (3,3)        1
   (1,4)        1
   (3,4)        1
   (4,4)        1
   (1,5)        1
   (2,5)        1

残念ながら、と の両方が大きいとbsxfun、メモリ不足になる可能性があります。メモリが問題になる場合は、またはの要素をループする必要がある場合があります。の頂点をループしてそれを行う 1 つの方法を次に示します。 size(A,1)numel(B)ABB

for i=1:numel(B), C{i} = find(any(A==B(i),2)); end

うん、簡単。cell 配列の増加は、データ自体を連続的に保持するのではなく、データへの連続した参照を格納するシーケンス コンテナーに似ているため、MATLAB では非常に高速です。おそらくismember、テストのボトルネックでした。

于 2013-10-04T05:09:41.307 に答える