【问题标题】:How to initialize a Matlab struct array for growing?如何初始化 Matlab 结构数组以进行增长?
【发布时间】:2019-02-01 00:30:50
【问题描述】:

增加一个数组,例如在循环中通过x = [x, a],在Matlab编程中通常不被接受,因为它会导致一个或多个调整大小操作,因此预分配通常是更好的选择。但是,在某些情况下,例如作为parfor 块中的reduction assignment,它可能具有优势。为此,必须将数组创建为零大小。对于数值数组,其表达式为[],对于元胞数组{}

对于结构数组,它不是那么明确。例如初始化为struct() 不会创建一个大小为零的结构数组,而是一个没有字段的 1x1 结构数组。这会导致错误

使用 horzcat 时出错
连接的结构体数组中的字段数不匹配。
结构体数组的串联要求这些数组具有相同的字段集。

在增长过程中,因为附加结构的字段结构与“无字段”结构不兼容。

如何初始化一个零大小的结构体数组以进行增长?

【问题讨论】:

  • 这个问题我遇到过很多次,现在终于弄明白了,所以想分享一下解决方案。
  • 你可以使用s = struct('field1', {}, 'field2', {})创建一个包含指定字段的0×0结构数组
  • 另外,x=x[x,a] 效率极低。使用x(end+1)=astackoverflow.com/a/48990695/7328782
  • @A.Donda 在这种情况下,struct([]) 创建一个没有字段的 0×0 结构数组
  • @LuisMendo,谢谢!我将您的 cmets 纳入答案。

标签: matlab struct


【解决方案1】:

原来答案是初始化为一个大小为零的数值数组x = []。即使它不是结构体数组,通过x = [x, a] 附加结构体a 也会生成一个1x1 结构体数组,可以附加具有相同字段的更多结构体。

这种不直观的行为似乎是 Matlab 语言的一般怪癖,因为 [] 是“灵活类型”。它最初是一个大小为零的双精度数组,但附加单数使其成为单个数组,附加元胞数组使其成为元胞数组。

正如@LuisMendo 在 cmets 中指出的那样,struct([]) 直接给出了一个没有字段的零大小结构数组。这种语法可能是首选的,因为它不太含糊。此外,s = struct('field1', {}, 'field2', {}) 可用于创建具有已定义字段的零大小结构数组。


我刚刚发现 @CrisLuengo 在 cmets 中的提议,通过分配附加到 end + 1 而不是串联,在“为增长而初始化”问题的上下文中不起作用。赋值不能改变结构的“类型”,它是由它的字段定义的。从无字段更改为要附加的任何结构的字段会导致错误“不同结构之间的下标分配”。 (但请参阅他的评论和我的澄清答案)

【讨论】:

  • “但附加单数使其成为单个数组,附加元胞数组使其成为元胞数组”。但你没有追加。你正在连接。你做[[],a],这对任何内置类型a都有效。附加是x(end+1)=a。该语法扩展了数组并将a 写入其中。您的语法会创建一个新数组,然后将其分配给xx 之前的类型与该分配无关。
  • 我在这里使用“追加”来表示“将 x 的原始值替换为包含原始值和另外一个新值的值”。它是通过连接实现的,虽然它可以通过赋值给 end+1 来实现,但这并没有减少附加——我指的是操作的结果。
  • 你指的是幕后发生的事情,好的。但这也不是那么明确。如果需要调整数组的大小以便分配给 end+1,它还会创建一个新数组。而在 parfor 循环中的归约赋值中,幕后发生的事情更加复杂——当然没有串联,因为 x 甚至不存在于生成 a 的 worker 上。
  • 我理解你的解释,但我认为合并它需要更复杂的措辞,而不会增加它的实际用途。我建议我保持原样,但是您的 cmets 可以作为背景信息?
  • 在这种情况下你也可以初始化为x=[],然后做if isempty(x), x = a; else x(end+1) = a; end。但是,是的,如果您不种植太多元素,那么差异并不重要。这与更大的数组相关(不取决于字段的数量,而是数组中元素的数量)。
【解决方案2】:

通过连接增加数组

x = [x, 0];

非常慢,请参阅herehere。相反,应该(如果由于某种原因无法进行预分配)通过添加一个新元素来增长数组,如下所示:

x(end+1) = 0;

原因是[x,0] 在每次循环迭代时创建了一个新数组,将旧数据复制到其中,而另一种形式扩展了数组,只是偶尔需要重新分配(当数组变得太小了)。

要初始化一个空结构数组(如suggested by @LuisMendo in a comment),可以这样做:

s = struct('field1', {}, 'field2', {});

要附加到它,请执行以下操作:

s(end+1) = struct('field1', 1, 'field2', 'x');

或者,可以附加

s(end+1).field1 = 5;
s(end).field2 = 'y';

请注意,在这种情况下,end+1 仅在首次将新元素附加到数组时发生,后续字段将写入最后一个数组元素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    • 2015-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多