问题描述
我在 Matlab 中有一个名为 s
的结构。这是一个包含两个字段 a
和 b
的结构。结构尺寸为 1 x 1,620,000。
这是一个非常大的结构(可能需要我机器的一半内存)。这是结构的样子:
我正在寻找一种有效的方法来将每个字段 a
和 b
连接成两个单独的数组,然后我可以将它们导出到 csv。为此,我构建了下面的代码,但即使在运行 12 小时后,它甚至还没有达到循环的四分之一。有没有更有效的方法?
a = [];
b =[];
total_n = size(s,2);
count = 1;
while size(s,2)>0
if size(s(1).a,1)
a = [a; s(1).a];
end
if size(s(1).b,1)
b = [b; s(1).b];
end
s(1) = []; %to save memory
if mod(count,1000) == 0
fprintf('Done %2f \n',[count/total_n])
end
count = count+1;
end
解决方法
s(1) = []; %to save memory
啊,但是评论是这么大的误解。
如果 size(s)
是 1 x 1,620,000,您只是突然强制循环执行(在引擎盖下,您看不到它)
snew=zeros(1,size(s,2)-1) # now you use double memory
snew=s(2:end) # now you force an unnecesary copy
因此,该行不仅使您的代码需要双倍的内存,而且在每个循环中,您都会创建一个大数组的不必要副本。
只需将您的 while
替换为普通的 for ii=1:size(s,2)
循环,然后索引 s
!
现在,您可以满怀希望地看到为什么以下同样是一个大错误(不仅如此,任何现代 MATLAB 版本目前都告诉您这是编辑器中的一个坏主意)
a=[]
a=[a;s(1).a]
在这里,在每个循环中,您都在强制 MATLAB 创建一个比以前大 1 的新 a
,并将旧 a
的内容复制到那里。
相反,预分配 a
的大小。
由于您不知道要在那里放什么,我建议使用元胞数组,因为每个 s(ii).a
都有不同的长度。
然后,您可以在循环之后,根据需要删除所有空 (isempty
) 单元格。
设法有效地做到了:
s= struct2cell(s);
s= squeeze(s);
a = a(1,:);
a = a';
a = vertcat(a{:});
b = a(2,:);
b = b';
b = vertcat(b{:});