matlab中的结构
Posted
技术标签:
【中文标题】matlab中的结构【英文标题】:structures in matlab 【发布时间】:2012-02-12 09:59:42 【问题描述】:%示例
clear all
a1 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a2 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a3 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a4 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
假设这些结构代表一个时间序列,其中 a1 代表 前 5 天(例如),a2 代表第 5-10 天,依此类推...我正在尝试 组合结构中的每个字段名,以便我有一个连续的系列(而不是将它们分成不同的结构。例如......
data1 = [a1.data1;a2.data1;a3.data1;a4.data1];
然后对data2和data3做同样的事情
最好的方法是什么?
【问题讨论】:
【参考方案1】:最好的方法是预先将结构定义为结构数组:
a(1) = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a(2) = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a(3) = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a(4) = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
这使您可以很容易地获取数据:
cat(1,a.data1)
但如果你坚持使用 N 个结构,那么试试这个:
function so3
a1 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a2 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a3 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a4 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
s1 = struct2cell(a1);
s2 = struct2cell(a2);
s3 = struct2cell(a3);
s4 = struct2cell(a4);
N = numel(fieldnames(a1));
data = cell([1 N]);
for i=1:N
datai = cell2mat(cellfun(@(x)xi',s));
end
end
【讨论】:
【参考方案2】:@Andrey 说得对,“最好的方法是预先将结构定义为结构数组”。他的回答是完整的。但是我不禁给出以下更紧凑的代码来处理“坚持使用 N 结构”的情况。它假定它们的名称都以 foo 开头,并以数字结尾,例如。 foo1、foo2、foo21,这将导致数据字段相对于 foo 名称按字母顺序堆叠。
% first make some data
foo1 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
foo2 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
foo3 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
foo4 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
现在我们得到工作区中以 foo 开头并以某个数字结尾的变量列表,并将它们放入一个单元格中,然后我们评估该单元格的逗号分隔连接,将 foo 设置为该值。
varstarter = 'foo';
varlist = who('-regexp', ['^' varstarter '[0-9]+']);
try
eval([varstarter '=[' sprintf('%s,',varlist:) '];']);
catch
warning('Could not concatenate variables starting with "%s".',varstarter);
end
这让我们可以直接使用@Andrey 的答案:
data1 = cat(1, foo.data1);
data2 = cat(1, foo.data2);
data3 = cat(1, foo.data3);
编辑(附录):您可以通过循环遍历 foo 的字段名称并将同名的变量分配给连接,使最后一步更加自动化。如果您想要不同的名称,则代码不难修改。也可以添加一个检查以确保该事物实际上具有字段。
if ~isstruct(foo)
warning('Variable "%s" is of an unexpected type.',varstarter);
else
varfields = fieldnames(foo);
for k=1:length(varfields)
eval([varfieldsk '=cat(1, ' varstarter '.' varfieldsk ');']);
end
end
本着避免显式循环的精神,因为它很有趣,下面是 else 语句中的位的等效代码:
varfields = repmat(fieldnames(foo)',2,1);
eval(sprintf(['%s=cat(1,' varstarter '.%s);'],varfields:));
【讨论】:
+1 - 真的很好!也许您应该添加一个案例来检查变量内的数据是否确实是预期的。一种防御性编程。 很好的答案。由此可以通过循环完成最后阶段。那么,首先使用 'fieldnames' 查找数组的名称,然后为每个数组生成一个类似于上图所示的变量? @Andrey 谢谢。我为连接添加了一个捕获,在新的“提取自动化”部分中,我在查找字段之前检查以确保它是一个结构。 @user1155751 是的,当然可以,如果我理解你的话。我在答案中添加了一小部分。以上是关于matlab中的结构的主要内容,如果未能解决你的问题,请参考以下文章