【问题标题】:Is there a way to vectorize struct(:).a(:,1) to array(:,:)?有没有办法将 struct(:).a(:,1) 向量化为 array(:,:)?
【发布时间】:2016-10-18 20:53:52
【问题描述】:

如果可能,我有兴趣将以下代码从for 循环转换为向量操作。前提是给定一个结构数组data,每个元素都有一个字段a,其中包含一个单列向量。所有字段a 上的所有列向量长度相同。我想从所有字段中获取每个列向量并将数据转换为一个矩阵,其中每一列包含来自该数组中字段a 的一个列向量。这意味着第一列应该是data(1).a,第二列应该是data(2).a,依此类推。

    % All arrays in 'data.a' are column vectors of equal length
    % (leaving 'numCols' in incase some genius can also make that general)
    [numRows,numCols] = size(data(1).a);

    % Pre-allocate for speed
    array1 = NaN(numRows,numCols);

    % Convert from struct to array
    for ii = 1:length(data)
        array1(:,ii) = data(ii).a;
    end

【问题讨论】:

    标签: matlab vectorization


    【解决方案1】:

    是的。做吧:

    array1 = [data.a];
    

    这很好,因为您甚至不需要知道列向量的大小或为构建预分配矩阵而产生的总列数(总列数实际上等于顺便说一句,结构数组中的元素总数)。事实上,由于我们直接构建矩阵,因此不再需要预先分配。您可以同时创建适量的空间并在一个步骤中使用内容填充矩阵。这是因为我们正在利用这样一个事实:data(ii).a 包含单个列,并且结构数组中 a 字段的所有列包含存储在字段 a 中的列向量中相同数量的行。

    执行data.a 会输出所谓的comma-separated list。这意味着执行data.a 相当于在 MATLAB 命令提示符下输入以下内容:

    >> data(1).a, data(2).a, data(3).a, ..., data(N).a
    

    如果您将data.a 放在一组方括号中,您实际上是在构建矩阵,一次查找一列。

    一个可重现的例子

    >> rng(123); clear data;
    >> data(1) = struct('a', rand(5, 1));
    >> data(2) = struct('a', rand(5, 1));
    >> data(3) = struct('a', rand(5, 1));
    

    data 包含一个三元素结构数组,其中一个字段a 包含一个随机的5 x 1 列向量。

    这是每个向量的样子:

    >> for ii = 1 : numel(data), disp(data(ii).a); end
    
    0.6965
    0.2861
    0.2269
    0.5513
    0.7195
    
    0.4231
    0.9808
    0.6848
    0.4809
    0.3921
    
    0.3432
    0.7290
    0.4386
    0.0597
    0.3980
    

    使用我给你的单行代码:

    >> array1 = [data.a]
    
    array1 =
    
        0.6965    0.4231    0.3432
        0.2861    0.9808    0.7290
        0.2269    0.6848    0.4386
        0.5513    0.4809    0.0597
        0.7195    0.3921    0.3980
    

    【讨论】:

    • 感谢您的帮助。我从来没有对逗号分隔列表感到陌生,但这解释了我过去的很多困惑。有一件事 - 我没有完全按照你的第一段。在第一句话中,您基本上是在说您不必担心预分配吗?关于利用我的领域的对称性,这似乎与您的第二句话不一致。此外,在括号中,“元素数量”是否与struc(numberOfElements) 相关?我从来没有完全熟悉讨论结构大小的词汇。
    • 不客气。逗号分隔的列表非常有用。你当然要担心预分配,但是因为我们是直接构建矩阵,所以不需要预分配。我实际上并没有说您通常不必担心预分配,但是对于这种情况,不需要考虑该主题。如果不清楚,我很抱歉。使用逗号分隔列表的结果是完整的矩阵。仅当您打算在循环中修改数组的内容时才使用预分配。因为你不再循环,所以不需要预先分配。
    • 另外,“元素数”只是结构数组的长度。您在结构数组中有N 元素,对吧?每个元素都包含一个列向量......所以你同意我的观点,列的总数就是结构元素的总数,N?在这种情况下,numCols = length(data); 其中length(data) = N;
    • 顺便说一句,我已经稍微编辑了我的帖子以避免您遇到的困惑。
    • 不幸的是,您无法在此处逃脱循环。执行data.a(1:100,3)data(1).a, data(2).a, ..., data(N).a(1:100,3) 相同。你所做的有点违反直觉,但事实就是如此。还有一种替代方法,您可以将所有矩阵连接在一起作为一个大矩阵,然后对正确数量的列进行二次采样。像array1 = [data.a]; array1 = array1(1:100,3:size(data(1).a,2):size(array1.2)); 这样的东西对连接在较大矩阵中的每个矩阵的每第三列进行二次采样并返回结果。不幸的是,这需要更多的内存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-05
    • 2019-03-10
    • 2021-06-10
    • 1970-01-01
    相关资源
    最近更新 更多