如何在Matlab中存储这个结构(整数列表的列表)? [英] How to store this structure (list of lists of integers) in Matlab?

查看:108
本文介绍了如何在Matlab中存储这个结构(整数列表的列表)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要存储整数列表的列表。例如, X [1] 应该能够包含 [1 3 5] X [2] 可以包含 [1 2] 。什么是最好的解决方案?一个单元格阵列?

I need to store a list of lists of integers. For example, X[1] should be able to contain [1 3 5] while X[2] could contain [1 2]. What's the best solution? A cell array?

后面的故事:

一个项目,我预先计算N行和M立方体之间的交集。这些被检索有两种方式:给定一个行索引,我想要一个它通过的多维数据集的列表,并给出一个多维数据集索引,我想要一个通过它的行的列表。

For a project, I pre-calculate the intersections between N lines and M cubes. These are retrieved in two ways: given a line index, I want a list of cubes that it passes through, and given a cube index, I want a list of lines that pass through it.

典型值为N = 2 ^ 24,M = 2 ^ 18,这意味着交叉矩阵(NxM)不在问题之中。幸运的是,平均线仅通过M ^(1/3)= 2 ^ 6立方体。目前,我将结构存储为NxM ^(1/3)矩阵,以便 X(n,...)是第n行通过的多维数据集的向量通过(用零填充)。

Typical values are N=2^24 and M=2^18, which means an intersection matrix (NxM) is out of the question. Fortunately, the average line passes through only M^(1/3)=2^6 cubes. Currently, I'm storing the structure as an NxM^(1/3) matrix, so that X(n,:) is a vector of cubes that the nth line passes through (padded with zeros).

对于给出列表索引的多维数据集,这样可以正常工作,但事实证明,我的代码的瓶颈是检索给定的行立方体索引。 (我使用 find(X == m)其中m是多维数据集索引。)我不能创建相反的矩阵,因为通过一个

This works fine for retrieving cubes given a list index, but it turns out that the bottleneck of my code is the retrieval of lines given a cube index. (I do it with find(X==m) where m is the cube index.) I can't create the opposite matrix, as the number of lines passing through a single cube can be very high, even though it is low on average.

推荐答案

通常,单元格数组

Generally a cell array is the right answer for this. This is the simplest case. Some example uses:

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

但是,这不是唯一的答案。

However, it is not the only answer.

您可以使用结构数组,每个结构都有一个名为 .indexes (或根据您的问题的适当名称)的字段。如果您想附加到列表列表中的附加信息,则可以更灵活地进行,例如多维数据集位置可以作为 .position 字段添加。示例用途:

You could use an array of structures, each with a field called .indexes (or an appropriate name based on your problem). This allows a little more flexibility if there is additional information you would like attached to your list of lists, for example cube position could be added as a .position field. Example uses:

%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个案例来说不实用)。这可能不是您的最佳答案,但参考实例使用如下:

You could also use a containers.Map object. This has the same advantages as an array of structures, but with greater flexibility in how you reference your objects. Whereas when using an array of structures is structure is references by an index, using a containers.Map object can reference each structure using an arbitrary number (not integers near 1), or a name (not practical for 2^24 cases). This is probably not the best answer for you, but for reference examples uses are below:

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

最后,可能值得为此定义一组自定义类 。这是一个更多的工作要设置,但可能是最简单的方式来获得恒定的时间查找到您的预先计算的值。一些代码让您开始下载此路径。

Finally, it may be worth defining a pair of custom classes for this. This is a bit more work to set up, but is probably the easiest way to get constant time lookups into your precalculated values. Some code to get you started down this path is below.

%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

使用这些类写成,你需要成对地调用添加方法(稍后的一个明显的升级是正确地交叉添加。在此期间(因为我很懒惰)我们将定义一个帮助函数。

To use these classes as written, you need to call the add methods in pairs (an obvious upgrade for later is to properly cross add. In the meantime (because I'm lazy), we'll define a helper function.

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)

BTW,我们真的只是采取这样的事实: handle 类表现为传递引用,因此我们可以使用复杂的交叉链接的数据结构。

BTW, we're really just taking advanatge of the fact that < handle classes behave as pass-by-reference, so we can use complex, cross-linked data structures.

这篇关于如何在Matlab中存储这个结构(整数列表的列表)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆