如果我想要将不同大小的字符串或矩阵存储在单个变量中,我可以考虑两种选择:我可以创建一个结构体数组,并让其中一个字段保存数据。
structArray(structIndex).structField
或者我可以使用一个单元数组,
cellArray{cellIndex}
但是否有通用的经验法则来决定使用哪种数据结构?我想知道在某些情况下使用其中一种有没有缺点。
在我看来,这更多是关于方便性和代码清晰度的问题。问问自己,你更喜欢通过数字还是名称来引用变量元素。如果是前者,请使用cell数组;如果是后者,请使用struct数组。可以想象一下有无标题的表格。
顺便提一下,您可以很容易地使用CELL2STRUCT和STRUCT2CELL函数在结构体和单元数组之间转换。
如果您在函数内使用它进行计算,我建议您使用cell数组,因为它们更方便处理,例如通过CELLFUN。
然而,如果您用它来存储数据(并返回输出),最好使用结构体,因为字段名称是(应该是)自说明的,所以您不需要记住您的cell数组第7列中有哪些信息。此外,您可以轻松地在结构体中包含一个“help”字段,可以在其中放置一些额外的字段解释,如果有必要的话。
结构体也对数据存储非常有用,因为如果您想在以后更新您的代码,可以将其替换为对象而无需更改您的代码(至少在您预先分配结构体的情况下)。它们具有相同的语法,但对象将允许您添加更多功能,例如依赖属性(即基于其他属性动态计算的属性)。
最后,请注意,单元格和结构体会为每个字段添加几个字节的开销。因此,如果您想使用它们处理大量数据,最好使用包含数组的结构体/单元格,而不是具有仅包含标量的结构体/单元格的大型数组。
这段代码表明,在赋值和检索时,单元数组的速度大约是结构体的两倍。我没有分离这两个操作。可以很容易地修改代码来实现。
运行"whos"之后,它们使用非常相似的内存量。
我的目标是用Python术语创建一个“列表的列表”,也许是“数组的数组”。
我希望这对您有趣/有用!
%%%%%%%%%%%%%% StructVsCell.m %%%%%%%%%%%%%%%
clear all
M = 100; % number of repetitions
N = 2^10; % size of cell array and struct
for m = 1:M
% Fill up a template cell array with
% lists of randomly sized matrices with
% random elements.
template{N} = 0;
for n = 1:N
r1 = round(24*rand());
r2 = round(24*rand());
r3 = rand(round(r2*rand),round(r1*rand()));
template{N} = r3;
end
% Make a cell array equivalent
% to the template.
cell_array = template;
% Create a struct with the
% same data.
structure = struct('data',0);
for n = 1:N
structure(n).data = template{n};
end
% Time cell array
tic;
for n = 1:N
data = cell_array{n};
cell_array{n} = data';
end
cell_time(m) = toc;
% Time struct
tic;
for n = 1:N
data = structure(n).data;
structure(n).data = data';
end
struct_time(m) = toc;
end
str = sprintf('cell array: %0.4f',mean(cell_time));
disp(str);
str = sprintf('struct: %0.4f',mean(struct_time));
disp(str);
str = sprintf('struct_time / cell_time: %0.4f',mean(struct_time)/mean(cell_time));
disp(str);
% Check memory use
whos
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
struct
在我的情况下快了四倍。 - embertstructScalar.structField(fieldIndex)
选项4:structScalar.structField{cellIndex}
在这四个选项中,#3对于大量元素具有最小的内存开销(它最小化了总矩阵数量),而当大量元素指的是>100,000时。如果您的代码适合在structField
上进行向量化,则可能是性能优势。如果无法将structField
的每个元素收集到单个矩阵中,则选项4具有符号优点,但没有选项3的内存和性能优势。这两个选项都可以更轻松地在整个数据集上使用arrayfun或cellfun,但代价是需要单独添加或删除每个字段的元素。选择取决于您如何使用数据,这让我们回到yuk的答案-选择使代码最清晰的选项。