如何获取这些数组并使用它们来填充结构的字段?
Posted
技术标签:
【中文标题】如何获取这些数组并使用它们来填充结构的字段?【英文标题】:How can I take these arrays and use them to populate the fields of a structure? 【发布时间】:2020-12-02 02:07:17 【问题描述】:我有几个向量,并想用它们来填充结构数组中的字段。向量只会有两种长度之一 - 它们的长度为 N 或长度为 1。例如,如果 N=3,我的向量可能如下所示:
a = [0 5 7]
b = [-2 6 8]
c = 6
d = [11 12 13]
e = 20
我希望结果是
my_structure(1).a = 0
my_structure(2).a = 5
my_structure(3).a = 7
my_structure(1).b = -2
my_structure(2).b = 6
my_structure(3).b = 8
my_structure(1).c = 6
my_structure(2).c = 6
my_structure(3).c = 6
my_structure(1).d = 11
my_structure(2).d = 12
my_structure(3).d = 13
my_structure(1).e = 20
my_structure(2).e = 20
my_structure(3).e = 20
您可以看到,对于仅初始长度为 1 的向量,结构数组的每个元素都应具有相同的值。
有没有一种简洁的方法来实现这一点而不必遍历每个元素?它应该是可扩展的,以便我可以添加更多向量 f,g,h,... 如果需要。
正如在 cmets 中查询的那样,我不能简单地使用 my_structure.a = [0 5 7]
等,因为我需要能够将 my_structure(i)
传递给另一个函数,这要求每个字段只包含一个值(而不是数组)。
【问题讨论】:
循环比这样的手写要简洁得多。在 MATLAB 中循环很慢是一个谬论,尤其是在最新的 JIT 更新之后。为什么循环不适合您的目的? 我不想这样手写 - 我只是写它来显示我希望每个查询的结果。 @Adriaan 我知道 Matlab 中有这些 arrayfun() 和 structfun() 函数,所以我怀疑有一种巧妙的方法可以使用它们来做到这一点。我一点也不担心循环变慢。 【参考方案1】:更新答案
事实证明,您可以利用文档中的这一行:
如果任何值输入是非标量元胞数组,则
s
与该元胞数组具有相同的维度。
所以
N = 3; % Each var has 1 or N elements
a = [0 5 7];
b = [-2 6 8];
c = 6;
% Create an anonymous function to make all vars the correct size CELL (1 or N)
pad = @(x) num2cell( repmat(x, 1, N/numel(x)) );
strct = struct( 'a', pad(a), 'b', pad(b), 'c', pad(c) );
这遵循与下面的原始答案类似的思维模式,但显然要简洁得多。
原答案
最简单的 详细的方法是从一个标量结构开始,然后将其转换为结构数组。所以...
N = 3; % Each var has 1 or N elements
a = [0 5 7];
b = [-2 6 8];
c = 6;
% Create an anonymous function to make all vars the correct size (1 or N)
pad = @(x) repmat(x, 1, N/numel(x));
% Create the scalar struct with padding
strctA = struct( 'a', pad(a), 'b', pad(b), 'c', pad(c) );
然后你可以有一个循环将它转换为一个结构数组,它与变量名没有联系,因此更容易维护:
f = fieldnames(strctA); % Get the field names, i.e. the original variable names
strctB = struct([]); % Create an output struct. The [] input makes it a struct array
for iFn = 1:numel(f) % Loop over the fields
for n = 1:N % Loop over the array elements
strctB(n).(fiFn) = strctA.(fiFn)(n); % Assign to new structure
end
end
【讨论】:
感谢您的回答。这实现了我想要的,但比我预期的要麻烦一些。我认为使用 arrayfun() 或 structfun() 可以在没有循环的情况下完成,从而减少代码行,但您的解决方案甚至使用两个嵌套循环。也许“最简单”和“简洁”是两个不同的东西。 @teeeeee 请看我的编辑,原来我很接近但有一个更简单的答案。 太棒了,很好的发现——我学到了一些东西!似乎即使您在创建结构时省略了 c 中的 pad() 函数,它仍然可以工作。虽然我猜最好保留它。谢谢! @teeeeee 是的,标量将被复制/分发,但您必须将所有数组转换为单元格,否则它们也将被复制/分发。我编写了pad
函数,以便它在两种情况下都有效,您不必关心输入变量的大小。如果您不想要一般性,您可以将其用于相同的结果:struct( 'a', num2cell(a), 'b', num2cell(b), 'c', c )
【参考方案2】:
Wolfie 的回答非常聪明,但您也可以使用更直接的解决方案,使用单个 for 循环:
N = 3;
a = [0 5 7]
b = [-2 6 8]
c = 6
d = [11 12 13]
e = 20
for i = 1:N
my_structure(i).a = a(min(length(a), i))
my_structure(i).b = b(min(length(b), i))
my_structure(i).c = c(min(length(c), i))
my_structure(i).d = d(min(length(d), i))
my_structure(i).e = e(min(length(e), i))
end
这种方法的优点是您的代码更易于阅读。
【讨论】:
以上是关于如何获取这些数组并使用它们来填充结构的字段?的主要内容,如果未能解决你的问题,请参考以下文章
我应该如何访问有关用于使用RxSwift和MVVM填充表格视图的数组的数据