假设我有一个struct array 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{:});
有什么想法吗?感谢。
答案 0 :(得分:11)
请注意,那里不需要deal
:
[arr.val] = newVals{:}; % achieves the same as deal(newVals{:})
我知道如何执行此操作的唯一其他方法(没有foor循环)是使用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){:}
这样的分层索引。
答案 1 :(得分:2)
我喜欢卡尔和math.coffee的原始想法。 我有多条类似的代码要表达,因此为了简化我的主代码, 我继续并做了通用子功能
function varargout = clist(in)
varargout = {in{:}};
end
然后我可以用一种易于阅读的方式来表达每一行
[arr.var] = clist(num2cell([arr.var]+3));
[arr.var2] = clist(num2cell([arr2.var]/5+33));
答案 2 :(得分:1)
该结构中的所有字段是标量还是相同的大小?如果是这样,惯用的Matlab方法是将结构重新排列为一个标量结构,在每个字段中都有数组,而不是字段中带有标量值的结构数组。然后,您可以对字段执行矢量化操作,例如arr.val = arr.val + 3;
。看看您是否可以重新排列数据。这样做在时间和记忆方面都更有效率;这可能就是为什么Matlab没有提供方便的语法来操作结构数组的字段。
答案 3 :(得分:0)
如果您尝试设置的struct数组是一组图形对象(行句柄,图形句柄,轴句柄等),那么您需要使用函数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