【发布时间】:2010-09-03 13:00:59
【问题描述】:
如果我想在一个变量中存储一些不同大小的字符串或矩阵,我可以考虑两种选择:我可以创建一个结构数组并让其中一个字段保存数据,
structArray(structIndex).structField
或者我可以使用元胞数组,
cellArray{cellIndex}
但是对于何时使用哪种数据结构有一个通用的经验法则吗?我想知道在某些情况下使用其中一种是否有缺点。
【问题讨论】:
如果我想在一个变量中存储一些不同大小的字符串或矩阵,我可以考虑两种选择:我可以创建一个结构数组并让其中一个字段保存数据,
structArray(structIndex).structField
或者我可以使用元胞数组,
cellArray{cellIndex}
但是对于何时使用哪种数据结构有一个通用的经验法则吗?我想知道在某些情况下使用其中一种是否有缺点。
【问题讨论】:
在我看来,这更多是为了方便和代码清晰。问问自己,您更喜欢按数字还是按名称来引用变量元素。然后在前一种情况下使用单元数组,在以后使用结构数组。想一想,就好像你有一个有和没有标题的表格。
顺便说一句,您可以使用CELL2STRUCT 和STRUCT2CELL 函数在结构和单元格之间轻松转换。
【讨论】:
如果您在函数中使用它进行计算,我建议您使用元胞数组,因为它们更方便处理,例如谢谢到CELLFUN。
但是,如果您使用它来存储数据(并返回输出),最好返回结构,因为字段名称(应该)是自记录的,因此您不需要记住您在单元格数组的第 7 列。此外,您可以轻松地在结构中包含一个“帮助”字段,如果需要,您可以在其中对这些字段进行一些额外的说明。
结构对于数据存储也很有用,因为如果您想在以后更新代码,可以用对象替换它们而无需更改代码(至少在您预先分配结构的情况下) .它们具有相同的语法,但对象将允许您添加更多功能,例如依赖属性(即基于其他属性动态计算的属性)。
最后,请注意单元格和结构会为每个字段增加几个字节的开销。因此,如果您想使用它们来处理大量数据,最好使用包含数组的结构/单元,而不是使用字段/元素仅包含标量的大型结构/单元数组。
【讨论】:
这段代码表明元胞数组的赋值和检索速度大约是结构体的两倍。我没有将这两个操作分开。可以很容易地修改代码来做到这一点。
之后运行“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 在我的情况下要快四倍
首先,我赞同 yuk 的回答。从长远来看,清晰度通常更为重要。
但是,根据数据的不规则形状,您可能还有两个选择:
选项 3:structScalar.structField(fieldIndex)
选项 4:structScalar.structField{cellIndex}
在这四个中,#3 对大量元素的内存开销最小(它最小化了矩阵的总数),我的意思是大于 100,000。如果您的代码适合在 structField 上进行矢量化,那么它也可能是性能上的胜利。如果您无法将structField 的每个元素收集到单个矩阵中,则选项 4 具有符号优势,但没有选项 3 的内存和性能优势。这两个选项都可以更轻松地在整个数据集上使用 arrayfun 或 cellfun,代价是要求您分别从每个字段中添加或删除元素。选择取决于您如何使用您的数据,这让我们回到 yuk 的答案——选择最清晰的代码。
【讨论】: