【问题标题】:MATLAB/OCTAVE Extracting elements from different sized vectors in a cell arrayMATLAB/OCTAVE 从元胞数组中不同大小的向量中提取元素
【发布时间】:2014-01-02 20:24:57
【问题描述】:

我有一个简单的问题,但我无法弄清楚或在任何地方找到它。 我有一个单元格数组,其中 c{1} 是一个向量,c{2} 是一个向量,但长度不同,最多为 c{i}。我想要的是一个向量,即 [c{1};c{2};c{3}...c{i}]。最有效的方法是什么?

【问题讨论】:

  • 如果 c{1},... 向量的长度不同,则不能将它们全部收集到一个向量/矩阵中。因为从一些向量制作矩阵需要这些向量的大小相同。
  • 我实际上想出了如何做到这一点,方法是在创建时将每个向量单独添加到大向量中。
  • 可以将不同长度的向量合并到一个向量中。如果你有 [1,2] 和 [3,4,5] 你可以把它们放在一起变成 [1,2,3,4,5]
  • 您在帖子中提到的与此示例不同,[c{1};c{2};c{3}...c{i}],您实际上是在添加每个一行中的向量,这使得使用不同长度的向量成为不可能。

标签: matlab octave cell-array


【解决方案1】:

以下单行甚至适用于完全不一致的输入:

result = [cell2mat(cellfun(@(x) x(:), A, 'uni', 0)')]'

示例:

为:

A{1} = [1, 2, 3, 4, 5];
A{2} = [6; 7; 8; 9];
A{3} = [10, 12; 11, 13];

它返回:

result =

     1     2     3     4     5     6     7     8     9    10    11    12    13

【讨论】:

    【解决方案2】:

    假设a 是一个仅包含列向量的结构,Matlab/Octave 允许这种非常不高效但非常方便的符号之王:

    x = [];             #% A fresh new vector/matrix/tensor, who knows?
    for i=1:numel(a)    #% parse container item by item
       x = [x;a{i}];    #% append container item a{i} to x in a column-fashion way
    end
    

    这可行,但效率极低,因为它将重新分配x 每个for 步骤,并且它不是防弹的(没有错误处理,没有类型检查):因此如果遇到任何东西(矩阵,字符串),它将失败, 行向量)但列向量很可能出现在此类容器中。

    无论如何,它会简化不那么严格和启发式的设计,但请考虑在需要稳健设计时重新实现。

    【讨论】:

    • 是的,这基本上就是我最终这样做的方式。唯一的区别是我在 x 中添加了 a 的每个元素,而不是一次创建所有元素,但时间相同。
    • 您的解决方案比上面的效率低(这已经不是有效的),因为每个数据而不是每个结构元素都会发生重新分配。更进一步,您应该首先解析结构以确定它包含多少元素,然后像以前一样填充您的向量。在for 语句中使用numel。
    • thewaywewalk 提供的解决方案优雅、高效、健壮。它只是使用应用于容器的每个元素的身份 lambda 函数。我的建议是:您应该将其标记为您问题的解决方案。
    【解决方案3】:

    您可以用零填充每个单元格,并将长度与最长的单元格向量对齐。它通过迭代每个单元向量在循环中完成。

    【讨论】:

      【解决方案4】:

      这取决于 c 中的向量是行向量还是列向量。但通常最快和最紧凑的方式是:

      c={[1 2 3], [4 5 6 7 8], [9 10]}
      cell2mat(c)
      cat(2, c{:})
      

      或

      c={[1 2 3]', [4 5 6 7 8]', [9 10]'}
      % cell2mat(c) % Doesn't work.
      cat(1, c{:})
      

      所以就个人而言,我更喜欢猫。

      【讨论】:

        【解决方案5】:

        在 Matlab 中;没有循环:

        1. 如果元胞数组包含 column 向量并且您想将它们排列成一个大的列向量:

          result = vertcat(c{:}); %// vertically concat all vectors
          

          例子:

          >> c = {[1;2], [1;2;3]};
          >> result = vertcat(c{:})
          result =
               1
               2
               1
               2
               3
          
        2. 如果元胞数组包含 行 向量,您可以将它们排列为矩阵的行,用NaN(或任何其他值)填充不存在的值:

          M = max(cellfun(@numel, c)); %// max length of vectors
          c2 = cellfun(@(row)[row NaN(1,M-numel(row))], c, 'uni', 0); %// fill with NaN
          result = vertcat(c2{:}); %// concat all equal-size row vectors into a matrix
          

          例子:

          >> c = {[1 2], [1 2 3]};
          >> M = max(cellfun(@numel, c));
          >> c2 = cellfun(@(row)[row NaN(1,M-numel(row))], c, 'uni', 0);
          >> result = vertcat(c2{:})
          result =
               1     2   NaN
               1     2     3
          

        【讨论】:

        • 这就是我想要的。谢谢!我还没有足够的代表来投票,但这正是我所需要的。
        • @user12550 很高兴我能帮上忙 :-)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-15
        相关资源
        最近更新 更多