2010-04-03 63 views
2

我正在分配一個3D數組,其中包含許多不同工況的一些信息。數組中的每一行定義了一個特定的工況(其中有3個),如果行(3D)中的所有元素都等於零,我想刪除工況(即行)。如何刪除元素總和爲零的數組維度?

我現在共有的代碼是:

Array = zeros(3,5) %# Initialise array 
Numloadcases = 3; 

Array(:,:,1) = [10 10 10 10 10; 
       0 0 0 0 0; 
       0 0 0 0 0;]; %# Expand to a 3D array 

Array(:,:,2) = [10 10 10 10 10; 
       0 0 0 0 0; 
       0 0 0 0 0;]; 

Array(:,:,3) = [10 10 10 10 10; 
       0 0 0 0 0; 
       0 0 20 0 0;]; 

Array(:,:,4) = [10 10 10 10 10; 
       0 0 0 0 0; 
       0 0 20 0 0;]; 

%# And to remove the second row: 

for i = 1:Numloadcases 
    if sum(Array(i,:,:)) == 0 
    Array(i,:,:) = []; 
    end 
end 

此刻,for循環我必須刪除的行引起的索引錯誤,因爲在迴路中的陣列的大小變化。

任何人都可以看到這方面的工作?

回答

3

下面是循環,使用功能ALLlogical indexing替代:

isAllZero = all(all(Array == 0,3),2); %# Logical index of rows with all zeroes 
Array = Array(~isAllZero,:,:); %# Keep rows that have non-zero values 
%# Or... 
Array(isAllZero,:,:) = [];  %# Set rows with all zeroes to the empty matrix 
0

MATLAB命令「任何」告訴您是否存在任何非零元素。 (Array(i,:,:) == 0)對於正負元素的某些混合物(例如[11-2])將產生真實值,這可能不是實現它的方式。

我很想聰明,告訴你如何做到這一點沒有for循環,但是這裏for循環的開銷很小,如果你保留for循環,代碼可能更清晰。你的錯誤是這行: Array(i,:,:) = [] 這可能會導致Matlab的你大吼有關的元素

的解決方法是跟蹤你要刪除的內容元素的數量不匹配,那麼照顧,在該循環

valid = false([1 Numloadcases]); %preallocate 
for i = 1:Numloadcases 
    valid(i) = any(any(Array(i,:,:))); 
end 
Array = Array(valid,:,:); 

如果數組是你可能不希望平鋪了一堆的任何命令的一般ND陣列,所以這個替代配方年底將工作

valid = false([1 Numloacases]); 
for i = 1:Numloadcases 
    valid(i) = any(reshape(Array(i,:,:), 1, []); 
end 
Array = Array(valid,:,:); 
+0

一個問題... '陣列(I,:,:)'實際上是一個3維數組(使用問題中的示例,1乘5乘4)。因此,您必須至少應用任意兩次:'valid(i)= any(any(Array(i,::)));'。 – gnovice 2010-04-04 04:16:45

+0

好抓!我修正了這個例子,並指出你也可以使用重塑。 – Marc 2010-04-04 14:44:05

+0

你應該也可以說「valid(i)= any(Array(i,:))」 – Nzbuu 2010-04-06 12:30:32