根据计数按元素复制数组

发布于 2024-08-24 15:43:37 字数 533 浏览 6 评论 0原文

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

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

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

My question is similar to this one, but I would like to replicate each element according to a count specified in a second array of the same size.

An example of this, say I had an array v = [3 1 9 4], I want to use rep = [2 3 1 5] to replicate the first element 2 times, the second three times, and so on to get [3 3 1 1 1 9 4 4 4 4 4].

So far I'm using a simple loop to get the job done. This is what I started with:

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

I managed to improve by preallocating space:

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

However I still feel there has to be a more clever way to do this... Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

就此别过 2024-08-31 15:43:37

这是我喜欢完成此任务的一种方法:

>> 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

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

Here's one way I like to accomplish this:

>> 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

This works by first creating an index vector of zeroes the same length as the final count of all the values. By performing a cumulative sum of the rep vector with the last element removed and a 1 placed at the start, I get a vector of indices into index showing where the groups of replicated values will begin. These points are marked with ones. When a cumulative sum is performed on index, I get a final index vector that I can use to index into v to create the vector of heterogeneously-replicated values.

摘星┃星的人 2024-08-31 15:43:37

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

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

这比 新手..

To add to the list of possible solutions, consider this one:

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

This is much slower than the one by gnovice..

や三分注定 2024-08-31 15:43:37

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

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

结果

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

请注意,此函数也执行相反的操作,即游程编码向量,或者换句话说,返回和相应的>计数

What you are trying to do is to run-length decode. A high level reliable/vectorized utility is the FEX submission rude():

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

the result

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

Note that this function performs the opposite operation as well, i.e. run-length encodes a vector or in other words returns values and the corresponding counts.

悲念泪 2024-08-31 15:43:37

如果 rep 数组中存在零,则可以使用 Accumarray 函数使代码工作。

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

accumarray function can be used to make the code work if zeros exit in rep array

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

This works similar to solution of gnovice, except that indices are accumulated instead being assigned to 1. This allows to skip some indices (3 and 6 in the example below) and remove corresponding elements from the output.

>> 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文