【问题标题】:Can the values of this structure be accessed/modified without using a for loop?可以在不使用 for 循环的情况下访问/修改此结构的值吗?
【发布时间】:2017-03-23 21:55:58
【问题描述】:

这是我的初始结构数组:

A(1).B.C = 'a';
A(2).B.C = 'b';
A(3).B.C = 'a';
A(4).B.C = 'a';

我想根据Values 的值和IndexingArray 的索引更改字段C 的值:

Values = {'a', 'b'};
IndexingArray = [1 1 0 1];

所以,我的新结构数组将是:

A(1).B.C = 'b';
A(2).B.C = 'b';
A(3).B.C = 'a';
A(4).B.C = 'b';

有没有办法在不使用 for 循环的情况下做到这一点?

【问题讨论】:

  • 这甚至不是一个信号处理问题。我想你是想在 StackOverflow 上问这个,然后在这里问你与阶段相关的 StackOverflow 问题!
  • 如果没有 for 循环,我想不出一种方法来做到这一点......有什么理由说明 for 循环不适合你吗?这不是矩阵,因此避免使用 for 循环(如果可能)不会有太大改进。

标签: matlab matlab-struct


【解决方案1】:

可以使用dealcomma separated list 语法在没有循环的情况下执行此操作,但它可能看起来有点难以阅读:

% Initialize A:
A(1).B.C = 'a';
A(2).B.C = 'b';
A(3).B.C = 'a';
A(4).B.C = 'a';
Values = {'a', 'b'};
IndexingArray = [1 1 0 1];

temp = [A.B];           % Structure array containing B substructures
[temp.C] = deal(Values{IndexingArray+1});  % Set field C of each structure element
temp = num2cell(temp);  % Convert to a cell array of 1-by-1 structures
[A.B] = deal(temp{:});  % Update B substructures

在较新版本的 MATLAB 中,您可以完全省略 deal

temp = [A.B];
[temp.C] = Values{IndexingArray+1};
temp = num2cell(temp);
[A.B] = temp{:};

这应该允许您更新BC 字段,而不会影响您的更复杂结构中可能存在的任何其他字段。

【讨论】:

    【解决方案2】:

    不改变值,重建结构数组更简单。

    • 通过IndexingArray获取价值:

      val = Values(IndexingArray+1);
      
    • 使用cell2struct 构建结构数组,并使用num2cell 转换为元胞数组:

      T = num2cell(cell2struct(val, {'C'}, 1));
      
    • 使用cell2structT结果转换为结构数组:

      A = cell2struct(T', {'B'}, 1);
      

    这里是创建 A 的代码示例:

    Values = {'a', 'b'};
    IndexingArray = [1 1 0 1];
    
    val = Values(IndexingArray+1);
    
    T = num2cell(cell2struct(val, {'C'}, 1));
    
    A = cell2struct(T', {'B'}, 1);
    

    在一行代码中构建 A:

    A = cell2struct((num2cell(cell2struct(Values(IndexingArray+1), {'C'}, 1)))', {'B'}, 1);
    

    结果(用于测试):

    >> A(1).B.C
    
    ans =
    
    b
    
    >> A(2).B.C
    
    ans =
    
    b
    
    >> A(3).B.C
    
    ans =
    
    a
    
    >> A(4).B.C
    
    ans =
    
    b
    

    使用arrayfun的解决方案:

    val = Values(IndexingArray+1);
    
    A = arrayfun(@(x) struct('B', struct('C', val{x})), 1:4)
    

    更新A的特定元素:

    如果您需要更新特定元素,而不是覆盖A,您可以选择性地将arrayfun 应用于索引,您知道您需要更新。

    例子:

    假设A长度为6个元素,需要更新前4个,可以使用如下代码:

    A(1:4) = arrayfun(@(x) struct('B', struct('C', val{x})), 1:4);
    

    假设你知道你只需要更新A(1)A(4),你可以使用下面的例子:

    A(1).B.C = 'a';
    A(2).B.C = 'b';
    A(3).B.C = 'a';
    A(4).B.C = 'a';
    A(5).B.C = 'c';
    A(6).B.C = 'd';
    
    Values = {'a', 'b'};
    IndexingArray = [1 1 0 1];
    
    val = Values(IndexingArray+1);
    
    %List of indices of A to update
    indices = [1, 4];
    
    A(indices) = arrayfun(@(x) struct('B', struct('C', val{x})), indices);
    

    【讨论】:

    • 我测试了你的最后一个解决方案,但它覆盖了整个结构 A。有没有办法更新特定字段,而不是覆盖结构 A?
    • 我更新了我的答案,如果这是你的意思,请告诉我。
    • 如果结构 A 有多个字段(例如,B 和 D),您的解决方案不起作用,因为我只想更新字段 B,但它会覆盖整个字段。我只想选择性地更新字段 B 和 C 而不是结构 A 或结构 B 拥有的任何其他字段
    • 我认为没有for 循环就没有办法做到这一点(可能有一种使用eval 的方法)。你喜欢我删除我的答案吗(给别人更好的机会回答)?
    • 在我删除我的答案之前,您能否修改您的答案:将您在 cmets 中编写的所有其他约束添加到您的帖子中。提及结构A 有多个字段(例如,BD)。提及您要更新特定字段。请给出一个反映所有这些要求的代码示例。考虑为您的问题发布一个使用 for 循环的解决方案...
    猜你喜欢
    • 2022-08-03
    • 1970-01-01
    • 1970-01-01
    • 2011-10-16
    • 2015-09-09
    • 2015-07-03
    • 2014-05-01
    • 2017-11-22
    • 1970-01-01
    相关资源
    最近更新 更多