根据计数的元素数组复制

时间:2010-03-04 20:00:18

标签: arrays matlab repeat run-length-encoding elementwise-operations

我的问题与此one类似,但我想根据在相同大小的第二个数组中指定的计数来复制每个元素。

一个例子,比如说我有一个数组v = [3 1 9 4],我想用rep = [2 3 1 5]来复制第一个元素2次,第二次复制三次,依此类推得到{{1} }。

到目前为止,我正在使用一个简单的循环来完成工作。这就是我的开始:

[3 3 1 1 1 9 4 4 4 4 4]

我设法通过预先分配空间来改进:

vv = [];
for i=1:numel(v)
    vv = [vv repmat(v(i),1,rep(i))];
end

然而,我仍然觉得必须有一个更聪明的方法来做到这一点......谢谢

4 个答案:

答案 0 :(得分:16)

这是我喜欢的一种方式:

>> index = zeros(1,sum(rep));
>> index(cumsum([1 rep(1:end-1)])) = 1;

index =

     1     0     1     0     0     1     1     0     0     0     0

>> index = cumsum(index)

index =

     1     1     2     2     2     3     4     4     4     4     4

>> vv = v(index)

vv =

     3     3     1     1     1     9     4     4     4     4     4

这首先创建一个零的索引向量,其长度与所有值的最终计数相同。通过执行rep向量的累积和,删除最后一个元素并在开始时放置1,我得到一个索引向量index,显示复制值组的开始位置。这些点标有一些。当对index执行累积求和时,我得到一个最终索引向量,我可以用它来索引v以创建异构复制值的向量。

答案 1 :(得分:2)

要添加可能的解决方案列表,请考虑以下问题:

vv = cellfun(@(a,b)repmat(a,1,b), num2cell(v), num2cell(rep), 'UniformOutput',0);
vv = [vv{:}];

这比gnovice ..

慢得多

答案 2 :(得分:0)

您要做的是游程解码。高级可靠/矢量化实用程序是FEX submission rude()

% example inputs
counts = [2, 3, 1];
values = [24,3,30];

结果

rude(counts, values)
ans =
    24    24     3     3     3    30

请注意,此函数也执行相反的操作,即游程编码一个向量,换句话说,返回values和相应的counts

答案 3 :(得分:0)

如果在accumarray数组中退出零,则可以使用

rep函数使代码工作

function vv = repeatElements(v, rep)
index = accumarray(cumsum(rep)'+1, 1);
vv = v(cumsum(index(1:end-1))+1);
end

这类似于gnovice的解决方案,除了索引被累积而不是分配给1.这允许跳过一些索引(下面示例中的3和6)并从输出中删除相应的元素。

>> v = [3 1 42 9 4 42];
>> rep = [2 3 0 1 5 0];
>> index = accumarray(cumsum(rep)'+1, 1)'

index =

     0     0     1     0     0     2     1     0     0     0     0     2

>> cumsum(index(1:end-1))+1

ans =

     1     1     2     2     2     4     5     5     5     5     5

>> vv = v(cumsum(index(1:end-1))+1)

vv =

     3     3     1     1     1     9     4     4     4     4     4