Matlab:将 ID 与数据集(例如结构)相关联?
Matlab: associating an ID with a dataset (e.g. struct)?
我正在为 Matlab 中的高阶有限元仿真算法开发某个功能,我想知道实现某项任务的好方法是什么。我相信我面临着一个有点普遍的问题,但在做了一些挖掘之后,我并没有真正找到一个好的解决方案。
基本上,我有一长串 ID(对应于我的网格上的某些节点),其中每个 ID 都与小数据集相关联。然后当我 运行 我的求解器时,我需要访问与这些节点关联的数据并更新数据(多次)。
因此,例如,假设这是我的这些特定节点的列表:
nodelist = [3 27 38] %(so these are my node ID's)
然后对于每个节点,我有以下关联的数据集
a (scalar)
b (5x5 double matrix)
c (10x1 double vector)
(a total of 36 double values associated with each node ID)
实际上,我当然会有一个长得多的节点 ID 列表和一个更大的与每个节点关联的数据集(但仍然只有双标量、矩阵和向量(没有字符、字符串等)) .
方法一
所以我想出的一种方法就是将所有内容都存储在二维双矩阵中,然后在需要时进行一些相对复杂的索引以访问我的数据。对于上面的示例,我的二维矩阵的大小为
size(2Dmat) = [length(nodelist), 36]
假设我想访问节点 ID 27 的 b(3,3),我将访问 2Dmat(2,14)。
原则上,这是可行的,但由于这种复杂的索引,代码不是很干净和可读(更不用说,当我更改数据集设置方式时,我需要重新调整整个索引代码)。
方法二
另一种方法是对节点列表中的每个节点使用某种结构:
a = 4.4;
b = rand(5,5);
c = rand(10,1);
s = struct('a',a,'b',b,'c',c)
然后我可以通过 s.b(3,3) 等访问数据。但我只是不知道如何将结构与节点 ID 相关联?
方法 3
我能想到的最后一件事是建立某种 SQL 数据库,但这似乎有点矫枉过正。此外,我需要我的代码尽可能快,因为我需要多次访问与这些选定节点关联的数据集中的这些字段,而且我想对数据库进行一些查询会减慢速度。
请注意,最终我会将代码从 Matlab 转换为 C/C++,因此我更愿意实现一些不严重依赖某些 Matlab 特定功能的东西。
那么,关于如何以干净的方式实现此功能有什么想法吗?我希望我的问题有道理并提前致谢!
方法 2 是最干净的,并且很容易转换为 C++。对于每个节点,您都有一个结构 s
,然后:
data(nodeID) = s;
就是所谓的结构数组。你索引为
data(id).b(3,3) = 0.0;
这假设 ID 是连续的,或者它们的值没有很大的差距。但这始终可以确保,如果需要,很容易重新编号节点 ID。
在 C++ 中,你有一个结构向量:
struct Bla{
double a;
double b[3][3];
double c[10];
};
std::vector<Bla> data(N);
或者在 C:
Bla* data = malloc(sizeof(Bla)*N);
(完成后不要忘记 free(data)
)。
然后,在 C 或 C++ 中,您可以这样访问元素:
data[id].b[2][2] = 0.0;
除了索引在 C++ 中从 0 开始,在 MATLAB 中从 1 开始之外,翻译很明显。
请注意,此方法在 MATLAB 中比方法 1 具有更大的内存开销,但在 C 或 C++ 中则不然。
方法 3 是个坏主意,它只会减慢您的代码速度而没有任何好处。
我认为最干净的解决方案,给定一组不连续的节点 ID,方法 2 使用 map container where your node ID is the key (i.e. index) into the map. This can be implemented in MATLAB using a containers.Map
object, and in C++ using the std::map
容器。例如,以下是在 MATLAB 中创建节点映射并将值添加到节点映射的方法:
>> nodeMap = containers.Map('KeyType', 'double', 'ValueType', 'any');
>> nodelist = [3 27 38];
>> nodeMap(nodelist(1)) = struct('a', 4.4, 'b', rand(5, 5), 'c', rand(10, 1));
>> nodeMap(3)
ans =
struct with fields:
a: 4.400000000000000
b: [5×5 double]
c: [10×1 double]
>> nodeMap(3).b(3,3)
ans =
0.646313010111265
在 C++ 中,您需要为要存储在地图中的数据类型定义结构或 class(例如 Node
)。这是一个示例(...
表示传递给 Node
构造函数的参数):
#include <map>
class Node {...}; // Define Node class
typedef std::map<int, Node> NodeMap; // Using int for key type
int main()
{
NodeMap map1;
map1[3] = Node(...); // Initialize and assign Node object
map1.emplace(27, std::forward_as_tuple<...>); // Create Node object in-place
}
我正在为 Matlab 中的高阶有限元仿真算法开发某个功能,我想知道实现某项任务的好方法是什么。我相信我面临着一个有点普遍的问题,但在做了一些挖掘之后,我并没有真正找到一个好的解决方案。
基本上,我有一长串 ID(对应于我的网格上的某些节点),其中每个 ID 都与小数据集相关联。然后当我 运行 我的求解器时,我需要访问与这些节点关联的数据并更新数据(多次)。
因此,例如,假设这是我的这些特定节点的列表:
nodelist = [3 27 38] %(so these are my node ID's)
然后对于每个节点,我有以下关联的数据集
a (scalar)
b (5x5 double matrix)
c (10x1 double vector)
(a total of 36 double values associated with each node ID)
实际上,我当然会有一个长得多的节点 ID 列表和一个更大的与每个节点关联的数据集(但仍然只有双标量、矩阵和向量(没有字符、字符串等)) .
方法一
所以我想出的一种方法就是将所有内容都存储在二维双矩阵中,然后在需要时进行一些相对复杂的索引以访问我的数据。对于上面的示例,我的二维矩阵的大小为
size(2Dmat) = [length(nodelist), 36]
假设我想访问节点 ID 27 的 b(3,3),我将访问 2Dmat(2,14)。
原则上,这是可行的,但由于这种复杂的索引,代码不是很干净和可读(更不用说,当我更改数据集设置方式时,我需要重新调整整个索引代码)。
方法二
另一种方法是对节点列表中的每个节点使用某种结构:
a = 4.4;
b = rand(5,5);
c = rand(10,1);
s = struct('a',a,'b',b,'c',c)
然后我可以通过 s.b(3,3) 等访问数据。但我只是不知道如何将结构与节点 ID 相关联?
方法 3
我能想到的最后一件事是建立某种 SQL 数据库,但这似乎有点矫枉过正。此外,我需要我的代码尽可能快,因为我需要多次访问与这些选定节点关联的数据集中的这些字段,而且我想对数据库进行一些查询会减慢速度。
请注意,最终我会将代码从 Matlab 转换为 C/C++,因此我更愿意实现一些不严重依赖某些 Matlab 特定功能的东西。
那么,关于如何以干净的方式实现此功能有什么想法吗?我希望我的问题有道理并提前致谢!
方法 2 是最干净的,并且很容易转换为 C++。对于每个节点,您都有一个结构 s
,然后:
data(nodeID) = s;
就是所谓的结构数组。你索引为
data(id).b(3,3) = 0.0;
这假设 ID 是连续的,或者它们的值没有很大的差距。但这始终可以确保,如果需要,很容易重新编号节点 ID。
在 C++ 中,你有一个结构向量:
struct Bla{
double a;
double b[3][3];
double c[10];
};
std::vector<Bla> data(N);
或者在 C:
Bla* data = malloc(sizeof(Bla)*N);
(完成后不要忘记 free(data)
)。
然后,在 C 或 C++ 中,您可以这样访问元素:
data[id].b[2][2] = 0.0;
除了索引在 C++ 中从 0 开始,在 MATLAB 中从 1 开始之外,翻译很明显。
请注意,此方法在 MATLAB 中比方法 1 具有更大的内存开销,但在 C 或 C++ 中则不然。
方法 3 是个坏主意,它只会减慢您的代码速度而没有任何好处。
我认为最干净的解决方案,给定一组不连续的节点 ID,方法 2 使用 map container where your node ID is the key (i.e. index) into the map. This can be implemented in MATLAB using a containers.Map
object, and in C++ using the std::map
容器。例如,以下是在 MATLAB 中创建节点映射并将值添加到节点映射的方法:
>> nodeMap = containers.Map('KeyType', 'double', 'ValueType', 'any');
>> nodelist = [3 27 38];
>> nodeMap(nodelist(1)) = struct('a', 4.4, 'b', rand(5, 5), 'c', rand(10, 1));
>> nodeMap(3)
ans =
struct with fields:
a: 4.400000000000000
b: [5×5 double]
c: [10×1 double]
>> nodeMap(3).b(3,3)
ans =
0.646313010111265
在 C++ 中,您需要为要存储在地图中的数据类型定义结构或 class(例如 Node
)。这是一个示例(...
表示传递给 Node
构造函数的参数):
#include <map>
class Node {...}; // Define Node class
typedef std::map<int, Node> NodeMap; // Using int for key type
int main()
{
NodeMap map1;
map1[3] = Node(...); // Initialize and assign Node object
map1.emplace(27, std::forward_as_tuple<...>); // Create Node object in-place
}