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中的结构的主要内容,如果未能解决你的问题,请参考以下文章

关于matlab程序中的结构体

matlab如何读取结构体中的数据,比如我想利用里面的数据画图

matlab中的结构:节省负载和工作

matlab中的结构

MATLAB如何提取结构体中数据

将数据放在matlab中的结构中?