2014-06-22 45 views
2

我不知道是否有可能得到不同大小的子陣列的最小/最大值 而不使用matlab中的循環。matlab:不帶循環的不同大小的子陣列的總和值

% create a 1D vector with arbitory floating point values 
A = rand(100,1,'double'); 

% get start indexes of sections of A (eg. A>0.9) 
pos01 = A>0.9; 
posIdx= [1;find(pos01);size(A,1)]; 

% if 1 or size(A,1) where not required, remove them 
posIdx = unique(posIdx); 

% min/max all sections: 
for ix=1:size(posIdx,1)-1 
    Amin(ix) = min(A(posIdx(ix):posIdx(ix+1))); 
    Amax(ix) = max(A(posIdx(ix):posIdx(ix+1))); 
end 

如果你有一個非常大的向量A和很多節,這最後一行可能會很慢。 我不知道如何在matlab中對這個循環進行矢量化。

我試圖想出使用arrayfun,remap,bsxfun等的解決方案。 但所有我能想到的解決方案,需要的部分,以相等的大小 - 這是不是這樣的:(

任何想法

最好, 延亨裏克

+0

你真的需要在最後/第一個元素中重疊的部分嗎? –

+0

我可以避免重疊。準媽媽正在完成這項工作。大。 –

回答

2

使用cumsumaccumarray

A = rand(100,1,'double'); 
pos01 = A > 0.9; 
subs = (pos01(1) == 0) + cumsum(pos01(:)); % convert posIdx to subs. note the special treatment of the first entry. 
Amin = accumarray(subs, A, [], @min); 
Amax = accumarray(subs, A, [], @max); 
+1

+1與accumarray很好地完成,可能比bsxfun實現快得多。 – bla

+0

您是否注意到OP與一個元素重疊了這些部分?除此之外,你的方法將是路要走(我正在寫一個基於這個答案,當我說你的) –

+0

@LuisMendo有趣的一點。我沒有注意到這個細節。它確實讓事情變得更加複雜......我會看看我能否修復。 – Shai

0

bsxfun的方法來取代你的for循環的一部分 -

t1 = bsxfun(@le,1:size(A,1),posIdx(2:end)) & bsxfun(@ge,1:size(A,1),posIdx(1:end-1)); 
t1 = t1'; 
t2 = A(:,ones(1,size(t1,2))).*t1; 
t2(~t1)=nan; 
Amin = nanmin(t2); 
Amax = nanmax(t2); 
+0

[tag:bsxfun]非常有趣,但是恐怕它不適合使用它:(a)由此產生的代碼很難理解。 (b)它使用了太多的內存o(n^2)。 – Shai

+0

@Shai感謝您的反饋。同意你的看法,這個問題看起來確實慢一些。但是,'bsxfun'將總是使用'​​o(n^2)',如果提供了足夠的計算資源和內存帶寬,它可能會有用。這個'o(n^2)'內存需求適用於所有使用'bsxfun'的解決方案。在解釋部分,有時我會讓提問者主動詢問代碼的特定部分,如果有任何查詢的話。 – Divakar

+0

事實上'bsxfun'將總是使用o(n^2),但在很多情況下它是有道理的:恐怕在這裏**並非如此**。我覺得這個**特定的**任務'bsxfun'不是正確的工具,對於許多其他許多任務'bsxfun'非常有用,我認爲每個Matlab程序員都應該讓自己熟悉。 – Shai