更新Matlab结构体数组中每个元素的一个字段

23
假设我有一个结构体数组 arr,其中每个元素都有许多字段,包括一个称为val的字段。 我想通过一定的常量来增加每个元素的val字段值,就像这样:
for i = 1:length(arr)
    arr(i).val = arr(i).val + 3;
end

这个显然可行,但我感觉应该有一种方法可以用一行代码完成(而且不需要for循环)。我想出来的最好解决方案是两行代码,并需要一个临时变量:

newVals = num2cell([arr.val] + 3);
[arr.val] = deal(newVals{:});
任何想法?谢谢。
4个回答

13

仅作一点提示,那里并不需要deal

[arr.val] = newVals{:}; % achieves the same as deal(newVals{:})

我知道的另一种方法(不使用for循环)是使用arrayfun迭代数组中的每个结构体:

% make a struct array
arr = [ struct('val',0,'id',1), struct('val',0,'id',2), struct('val',0,'id',3) ]

% some attempts
[arr.val]=arr.val; % fine
[arr.val]=arr.val+3; % NOT fine :(

% works !
arr2 = arrayfun(@(s) setfield(s,'val',s.val+3),arr)

上述命令循环遍历arr中的每个结构体,并返回一个新的结构体,其中s.val已设置为s.val=3

我认为这实际上比您之前的两行代码和for循环不够高效,因为它返回了arr副本,而不是就地操作。

(很遗憾,Matlab不支持分层索引,例如[arr.val]=num2cell([arr.val]+3){:}。)


谢谢你提供有关deal的提示。我不知道setfield,所以它似乎可以在一行中完成,但正如你所说,这肯定比for循环解决方案更糟糕。至于像那样进行索引,我之前研究过;基本上,Mathworks声称支持任何类似的东西都会强制对解析器进行兼容性破坏性更改。这很遗憾,因为每次编写任何Matlab代码时,它几乎都会让我感到困扰。 - Carl
谢谢您的回答!在MATLAB 2013b中,[arr.val] = newVals {:}可以工作,但是arr.val = newVals {:}不行。在这种情况下,方括号到底起什么作用? - Berk U.
arrayfun在MATLAB中只是一个包装器,实际上你仍然在使用循环,虽然它们是伪装的。 - Adriaan
1
在结构体数组中使用deal函数的一个场景是当你想要给每个元素的某个字段赋相同的值时。例如,如果v = 9,你可以写成[arr.val] = deal(v);来将9赋值给结构体数组arr中每个元素的val字段。 - Luca Citi
1
[arr.val] = newVals{:}; 可以正常工作,但是 [arr.val] = newVals(:); 不行 - 假设 newVals 是一个向量而不是一个 cell 数组。有人能解释一下吗?! - user2305193

2

我喜欢Carl和mathematical.coffee的原创想法。 为了简洁我的主线代码,我有多个类似的行来表达, 所以我继续制作通用子函数。

function varargout = clist(in)
varargout = {in{:}};
end

然后我可以以相当易读的方式表达每一行。
[arr.var]  = clist(num2cell([arr.var]+3));  
[arr.var2] = clist(num2cell([arr2.var]/5+33));  

1

那个结构体中的所有字段都是标量,还是大小相同的吗?如果是这样,使用惯用的 Matlab 方法是将您的结构重组为具有每个字段中的数组的标量结构,而不是具有字段中标量值的结构数组。然后,您可以对字段执行矢量化操作,例如 arr.val = arr.val + 3;。看看您是否可以重新排列数据。以这种方式进行操作在时间和内存方面都更加高效;这可能是为什么 Matlab 不提供用于操作结构体数组字段的便捷语法的原因。


0

如果你要设置的结构体数组是一组图形对象(线条句柄、图形句柄、坐标轴句柄等),那么你需要使用函数set

x = (1:10)';
Y = rand(10,5);
l = plot(x,Y,'-k'); % returns an array of line handles in l
set(l,'Color','r'); % sets the property 'Color' for all the five lines in l

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接