这个问题在这里已经有一个答案:

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

一个例子,说我有一个数组 v = [3 1 9 4], ,我想使用 rep = [2 3 1 5] 复制第一个元素2次,第二次三次,依此类推 [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

我设法通过预先关注空间来改进:

vv = zeros(1,sum(rep));
c = cumsum([1 rep]);
for i=1:numel(v)
    vv(c(i):c(i)+rep(i)-1) = repmat(v(i),1,rep(i));
end

但是我仍然觉得必须有一种更聪明的方法来做到这一点...谢谢

有帮助吗?

解决方案

这是我喜欢做到这一点的一种方法:

>> 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 创建异质复制值的向量。

其他提示

要添加到可能的解决方案列表中,请考虑这一点:

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

这比一个慢得多 gnovice..

您要做的是 运行长度解码. 。高级可靠/矢量化的实用程序是 FEX提交 rude():

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

结果

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

请注意,此功能也执行相反的操作,即 运行长度编码 向量或换句话说返回 values 和相应的 counts.

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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top