我的问题与此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
然而,我仍然觉得必须有一个更聪明的方法来做到这一点......谢谢
答案 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