从Matlab中的数组中提取数字块

Extract blocks of numbers from array in Matlab

我有一个向量,我想从中提取所有块:

x = [1 1 1 4 4 5 5 4 6 1 2 4 4 4 9 8 4 4 4 4]

这样我就能得到向量或包含块的单元格:

[1 1 1], [4 4], [5 5], [4], [6], [1], [2], [4 4 4], [9], [8], [4 4 4 4]

有没有不使用 for 循环的有效方法?谢谢!

For 循环并不像您想象的那么慢,尤其是在较新的 Matlab 版本中,尤其是在我们的例子中。也许这会有所帮助

x = [1 1 1 4 4 5 5 4 6 1 2 4 4 4 9 8 4 4 4 4];

breakIdx = [0, find(diff(x)), length(x)];
groups = mat2cell(x,1,diff(breakIdx));

我们通过应用 diff(x) 找到组,并使用 find() 获得组索引。然后只需将组移动到生成的单元格中即可 groups.

这里很少检查边界情况,所以我建议您添加它。

您可以使用 accumarray with a custom anonymous function:

y = accumarray(cumsum([true; diff(x(:))~=0]), x(:), [], @(x) {x.'}).';

这给出了一个向量元胞数组。在你的例子中,

x = [1 1 1 4 4 5 5 4 6 1 2 4 4 4 9 8 4 4 4 4];

结果是

y{1} =
     1     1     1
y{2} =
     4     4
y{3} =
     5     5
y{4} =
     4
y{5} =
     6
y{6} =
     1
y{7} =
     2
y{8} =
     4     4     4
y{9} =
     9
y{10} =
     8
y{11} =
     4     4     4     4

如果在元胞数组中保存所有块不是那么重要,而是关于它们的完整信息,您可以使用此代码:

x = [1 1 1 4 4 5 5 4 6 1 2 4 4 4 9 8 4 4 4 4];
elements = x(diff([0 x])~=0);
block_size = accumarray(cumsum(diff([0 x])~=0).',1).';
blocks = [elements; block_size];

获取双行矩阵,其中元素在第一行,块大小在第二行:

blocks =
     1     4     5     4     6     1     2     4     9     8     4
     3     2     2     1     1     1     1     3     1     1     4

然后定义一个函数来根据需要创建这些块:

getBlock = @(k) ones(1,blocks(2,k))*blocks(1,k);

并用你想要的块数调用它:

getBlock(8)

获得:

ans =
     4     4     4