3

整数のリストのリストを保存する必要があります。たとえば、を含むことができる一方X[1]で、 を含むことができる必要があります。最善の解決策は何ですか? セル配列?[1 3 5]X[2][1 2]


バックストーリー:

プロジェクトでは、N 個の線と M 個の立方体の交点を事前に計算します。これらは 2 つの方法で取得されます。ライン インデックスを指定すると、それが通過するキューブのリストが必要になり、キューブ インデックスを指定すると、それを通過するラインのリストが必要になります。

典型的な値は N=2^24 および M=2^18 であり、これは交差行列 (NxM) が問題外であることを意味します。幸いなことに、平均線は M^(1/3)=2^6 キューブしか通過しません。現在、構造を NxM^(1/3) 行列として格納しているため、これX(n,:)は n 番目の行が通過する (ゼロで埋められた) 立方体のベクトルです。

これは、リスト インデックスを指定してキューブを取得する場合には問題なく機能しますが、私のコードのボトルネックは、キューブ インデックスを指定して行を取得することであることがわかりました。(find(X==m)ここで、m はキューブ インデックスです。) 反対の行列を作成することはできません。1 つのキューブを通過するラインの数は、平均的には低くても、非常に多くなる可能性があるためです。

4

1 に答える 1

11

一般に、セル配列がこれに対する正しい答えです。これは最も単純なケースです。いくつかの使用例:

%Writes
X = {[1], [1 2 3], [1 2]};
X{4} = [1 2 3 4];

%Reads
a = X{1}
b = cat(2,X{:});
c = X([2 4]);

しかし、それだけが答えではありません。

構造体の配列を使用でき、それぞれにフィールドが呼び出され.indexesます (または問題に基づいた適切な名前)。これにより、リストのリストに添付したい追加情報がある場合に、もう少し柔軟性が得られます。たとえば、キュ​​ーブの位置を.positionフィールドとして追加できます。使用例:

%Writes
X(1).indexes = 1;
X(2).indexes = [1 2 3];
X(3).indexes = [1 2];

%Reads
a = X(1).indexes
b = cat(2,X.indexes)
c = X([2 4]);

container.Mapオブジェクトを使用することもできます。これには、構造体の配列と同じ利点がありますが、オブジェクトを参照する方法がより柔軟になります。構造体の配列を使用する場合、構造体はインデックスによって参照されますが、コンテナーを使用すると、Map オブジェクトは任意の数 (1 に近い整数ではない) または名前 (2^24 の場合は実用的ではありません) を使用して各構造体を参照できます。これはおそらくあなたにとって最良の答えではありませんが、参考例として以下に使用例を示します。

%Writes
X = containers.Map('keyType','uint32','valueType','Any');
X(1) = [1];
X(2) = [1 2 3];
X(3) = [1 2];
X(4) = [1 2 3 4];

%Reads
a = X(1);
b = cat(2,X.values);

最後に、このためにカスタム クラスのペアを定義する価値があるかもしれません。これはセットアップに少し手間がかかりますが、事前に計算された値を一定時間ルックアップする最も簡単な方法です。このパスを開始するためのコードを以下に示します。

%A start at cube.m.  Most of the code handles smartly reallocating the list of lines.
classdef cube < handle
    properties (SetAccess = private, GetAccess = public)
        numLines = 0
        intersectingLines = [];
    end
    methods (Access = public)
        function addLine(self, lineToAdd)
            if self.numLines == 0
                self.intersectingLines = lineToAdd;
                self.numLines = 1;
            elseif self.numLines>=length(self.intersectingLines)
                self.intersectingLines(length(self.intersectingLines)*2) = line();
                self.intersectingLines(self.numLines+1) = lineToAdd;
                self.numLines = self.numLines+1;
            else
                self.intersectingLines(self.numLines+1) = lineToAdd;
                self.numLines = self.numLines+1;
            end
        end
    end
end

%A start at line.m.  A near copy/paste of cube.m
    classdef line < handle
    properties (SetAccess = private, GetAccess = public)
        numCubes = 0
        intersectingCubes = [];
    end
    methods (Access = public)
        function addCube(self, cubeToAdd)
            if self.numCubes == 0
                self.intersectingCubes = cubeToAdd;
                self.numCubes = 1;
            elseif self.numCubes>=length(self.intersectingCubes)
                self.intersectingCubes(length(self.intersectingCubes)*2) = cube();
                self.intersectingCubes(self.numCubes+1) = cubeToAdd;
                self.numCubes = self.numCubes+1;
            else
                self.intersectingCubes(self.numCubes+1) = cubeToAdd;
                self.numCubes = self.numCubes+1;
            end
        end
    end 
end

これらのクラスを記述どおりに使用するには、addメソッドをペアで呼び出す必要があります (後の明らかなアップグレードは、適切に相互追加することです。それまでの間 (私は怠け者なので)、ヘルパー関数を定義します。

function crossAdd(cube, line)
cube.addLine(line);
line.addCube(cube);

使用例は次のとおりです。

%Create two class arrays of cubes and lines
allCubes(1) = cube;
allCubes(2) = cube;
allCubes(3) = cube;
allCubes(4) = cube;

allLines(1) = line;
allLines(2) = line;
allLines(3) = line;
allLines(4) = line;

%Define links (matching above "writes" examples)
crossAdd(allCubes(1), allLines(1));
crossAdd(allCubes(2), allLines(1));
crossAdd(allCubes(2), allLines(2));
crossAdd(allCubes(2), allLines(3));
crossAdd(allCubes(3), allLines(1));
crossAdd(allCubes(3), allLines(2));
crossAdd(allCubes(4), allLines(1));
crossAdd(allCubes(4), allLines(2));
crossAdd(allCubes(4), allLines(3));
crossAdd(allCubes(4), allLines(4));

%Use linked values
aLines = allCubes(1).getLines   %Only one intersecting line
bLines = allCubes(2).getLines   %Three intersecting lines
cubesFromSecondLine = bLines(2).getCubes %Three cubes here (2, 3, 4)

ところで、クラスが参照渡しとして動作するという事実を< handle利用しているだけなので、複雑な相互リンクされたデータ構造を使用できます。

于 2012-12-07T16:15:40.123 に答える