结构的Matlab数组:快速赋值

时间:2011-10-28 06:59:08

标签: arrays matlab struct variable-assignment vectorization

有没有办法“vector”分配一个struct数组。

目前我可以

edges(1000000) = struct('weight',1.0); //This really does not assign the value, I checked on 2009A.
for i=1:1000000; edges(i).weight=1.0; end; 

但这很慢,我想做更像

的事情
edges(:).weight=[rand(1000000,1)]; //with or without the square brackets. 

任何有关此任务的矢量化的想法/建议,以便更快。

提前致谢。

6 个答案:

答案 0 :(得分:13)

这比交易或循环要快得多(至少在我的系统上):

N=10000;
edge(N) = struct('weight',1.0); % initialize the array
values = rand(1,N);  % set the values as a vector

W = mat2cell(values, 1,ones(1,N)); % convert values to a cell
[edge(:).weight] = W{:};

在右边使用花括号给出了W中所有值的逗号分隔值列表(即N个输出),右边使用方括号将N个输出分配给edge(:)中的N个值。 / p>

答案 1 :(得分:9)

您可以尝试使用Matlab函数deal,但我发现它需要稍微调整一下输入(使用这个问题:In Matlab, for a multiple input function, how to use a single input as multiple inputs?),也许有一些更简单的事情。

n=100000;
edges(n)=struct('weight',1.0);
m=mat2cell(rand(n,1),ones(n,1),1);
[edges(:).weight]=deal(m{:});

此外,我发现这并不像我的计算机上的for循环那么快(约为0.35秒,交易约为0.05秒)可能是因为调用了mat2cell。如果你不止一次使用它,速度的差异会减少,但它仍然支持for循环。

答案 2 :(得分:7)

你可以写一下:

edges = struct('weight', num2cell(rand(1000000,1)));

答案 3 :(得分:2)

是否有什么要求你以这种方式特别使用结构?

考虑用结构的每个成员单独一个单独的数组替换你的结构数组。

weights = rand(1, 1000);

如果你有一个结构成员是一个数组,你可以做一个额外的维度:

matrices = rand(3, 3, 1000);

如果您只想保持整洁,可以将这些数组放入结构中:

edges.weights = weights;
edges.matrices = matrices;

但是如果你需要保留一组结构,我认为你可以做到

[edges.weight] = rand(1, 1000);

答案 4 :(得分:1)

您的示例中的结构未正确初始化的原因是您使用的语法仅解决结构数组中的最后一个元素。对于不存在的数组,其余部分将隐式填充在其所有字段中具有默认值[]的结构。

要明确此行为,请尝试使用clear edges; edges(1:3) = struct('weight',1.0)执行短数组并查看edges(1)edges(2)edges(3)中的每一个。 edges(3)元素的重量为1.0,如您所愿;其他人有[]

有效初始化结构数组的语法就是其中之一。

% Using repmat and full assignment
edges = repmat(struct('weight', 1.0), [1 1000]);

% Using indexing
% NOTE: Only correct if variable is uninitialized!!!
edges(1:1000) = struct('weight', 1.0);  % QUESTIONABLE

在索引未初始化的边数组时,请注意1:1000而不是1000

edges(1:1000)表格存在问题:如果edges已初始化,则此语法只会更新所选元素的值。如果edge有超过1000个元素,则其他元素将保持不变,并且您的代码将出错。或者,如果edges是不同的类型,则可能会出现错误或奇怪的行为,具体取决于其现有的数据类型。为安全起见,您需要在使用索引语法初始化之前执行clear edges。因此,最好只使用repmat表单进行完整作业。

但是无论你如何初始化它,像这样的数组结构对于更大的数据集来说总是很慢。你不能对它进行真正的“矢量化”操作,因为你的原始数组都被分解成每个struct元素中的mxArrays。这包括你问题中的字段分配 - 无法对其进行矢量化。相反,你应该像Brian L.的答案所说的那样切换一个数组结构。

答案 5 :(得分:0)

您可以使用反向结构,然后执行所有操作而不会出现任何错误 像这样

x.E(1)=1;
x.E(2)=3;
x.E(2)=8;
x.E(3)=5;

然后执行如下操作

x.E

ans =

    3     8     5

或者像这样

x.E(1:2)=2

x = 

    E: [2 2 5]

或者这个

x.E(1:3)=[2,3,4]*5

x = 

    E: [10 15 20]

它真的比for_loop快,你不需要其他大功能来减慢你的程序。