【问题标题】:Element-wise array replication according to a count [duplicate]根据计数的元素数组复制[重复]
【发布时间】:2011-01-23 20:23:55
【问题描述】:

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

举个例子,假设我有一个数组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

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

【问题讨论】:

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您要做的是运行长度解码。高级可靠/矢量化实用程序是 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】:

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

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

      这比gnovice.. 的速度慢得多。

      【讨论】:

      【解决方案4】:

      这是我喜欢的一种方法:

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

      【讨论】:

      • 你能补充一些关于它是如何工作的cmets吗?
      • @Nathan:已经在你前面了。 =)
      • 绝对是使用 cumsum.. 的聪明方法。谢谢!
      • 小心,这个解决方案只有在rep 的所有元素都是正数时才有效。如果您不想通过将rep 的某些元素设置为零来重复某些元素,它将失败。 v = [3 1 9 4]rep = [2 3 1 0] 结果为 [3 3 1 1 1 9 4],提供了一个额外的元素。
      猜你喜欢
      • 2011-06-22
      • 2021-02-11
      • 2020-11-12
      • 2023-03-30
      • 2010-12-12
      • 2016-03-07
      • 1970-01-01
      • 1970-01-01
      • 2016-04-21
      相关资源
      最近更新 更多