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

时间:2012-02-15 23:17:24

标签: arrays matlab struct field assign

假设我有一个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{:});

有什么想法吗?感谢。

4 个答案:

答案 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