2012-12-07 33 views
3

我需要存儲整數列表的列表。例如,X[1]應該能夠包含[1 3 5],而X[2]可能包含[1 2]。什麼是最好的解決方案?單元陣列?如何在Matlab中存儲這個結構(整數列表的列表)?


後面的故事:

對於一個項目,我預先計算N行和M立方體之間的交叉點。這些檢索有兩種方式:給定一個行索引,我想要一個它通過的多維數據集列表,並給定一個多維數據集索引,我想要一個通過它的行列表。

典型值爲N = 2^24和M = 2^18,這意味着交集矩陣(NxM)不存在問題。幸運的是,平均線只經過M ^(1/3)= 2^6立方體。目前,我將結構存儲爲NxM ^(1/3)矩陣,因此X(n,:)是第n行穿過的立方體的向量(用零填充)。

這適用於檢索給定列表索引的多維數據集,但事實證明,我的代碼的瓶頸是給定多維數據集索引的行的檢索。 (我用find(X==m)這樣做,其中m是立方體索引。)我無法創建相反的矩陣,因爲穿過單個立方體的線條數量可能非常高,即使它平均低。

回答

10

一般單元陣列是正確的答案。這是最簡單的情況。一些示例使用:

%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]); 

你也可以使用一個containers.Map對象。這與結構數組具有相同的優點,但在引用對象方面具有更大的靈活性。而當使用結構數組時,結構是通過索引來引用,使用containers.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類表現爲傳遞通過引用,所以我們可以使用複雜,交叉advanatge鏈接的數據結構。

相關問題