8

我的問題與此one類似,但我想根據在相同大小的第二個數組中指定的計數複製每個元素。根據計數的元素明智的陣列複製

這樣的一個例子,說我有一個數組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 

不過,我還是覺得必須有一個更聰明的方式來做到這一點...謝謝

+5

看到http://stackoverflow.com/questions/1975772/matlab-array-manipulation – Doresoom 2010-03-04 20:27:52

+1

@Doresoom:我想我之前已經回答這樣的問題,但無法找到它。我終於在同一時間追捕它。標題和標籤是完全不同的,這使得它有點難以找到。 – gnovice 2010-03-04 20:28:46

回答

15

這裏有我喜歡做到這一點的一種方法:

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

這工作首先創建澤的索引矢量roes的長度與所有值的最終數量相同。通過執行rep向量與最後一個元素的去除和1開始處的累積和,我得到一個指數向量index,顯示重複值組的開始位置。這些點用1標記。當在index上執行累計和時,我得到一個最終索引向量,我可以用它來索引v來創建異質複製值的向量。

+0

你可以添加一些如何工作的意見? – 2010-03-04 20:20:18

+0

@Nathan:已經領先於你了。 =) – gnovice 2010-03-04 20:23:22

+1

絕對是一個聰明的方式使用'cumsum' ..謝謝! – merv 2010-03-04 20:28:00

2

爲了增加可能的解決方案列表,看看這個例子:

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

這是一個比由gnovice慢得多..

+2

你實際上可以使用ARRAYFUN並避免對NUM2CELL的調用,但它仍然會* *更慢:http://stackoverflow.com/questions/1975772/matlab-array-manipulation/1975835#1975835。 – gnovice 2010-03-04 21:59:11

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

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