2017-02-20 103 views
1

我試圖達到的具體任務是很難描述,所以這裏有一個例子:給定A和X只比較非零元素

A = [1 2; 
    3 0; 
    3 5; 
    4 0]; 

x = [1 2 3]; 

我想要的算法,輸出

output: [1 2] 

這意味着A中第1行和第2行中的所有非零元素都在x中。

我已經這樣做了使用電池陣列和循環;然而,A和X非常大,我的方法並不高效。此外,我似乎無法弄清楚如何返工是爲了給我想要的東西。什麼是最快/最不佔用內存的方法?

編輯:道歉,我原來的例子是過於簡單化。現在已經糾正了。

回答

4

第一個答案是好的,但我會建議到不是使用arrayfun。有更多雄辯的方法來做你所要求的。使用ismemberall結合,然後在完成後將其索引到矩陣A中。基本上,你的問題是確定一行是否具有x中的所有值,並忽略零值。在這種情況下,我們可以找到矩陣A中實際爲零的所有值,然後使用它來增加我們的結果。

使用A作爲第一輸入和x作爲第二輸入將返回相同的尺寸A是否在A一個元件在x發現告訴你的矩陣。如果要檢查是否爲連續矩陣A所有元素可以在x發現,檢查是否行中的所有元素1。在此之上,找出所有零元素,然後用ismember輸出這些設置爲1,可以使用一個logical OR來完成。之後,您可以使用all並通過使用ismember的輸出作爲all的第一個輸入並將第二個參數設置爲2來獨立檢查每一行。然後這將返回矩陣A中的所有行,其中任何列都位於x忽略是零爲A行這是你要尋找的任何值:

A = [1 2; 3 0; 4 0]; 
x = [1 2 3]; 
mask = ismember(A, x); 
ind = all(mask | A == 0, 2); 

我也是贊成的俏皮話。我們可以將它合併爲一行代碼:

ind = all(ismember(A, x) | A == 0, 2); 

更簡單的是簡單地反轉A。所有非零元素成爲truefalse否則:

ind = all(ismember(A, x) | ~A, 2); 

ind因此將是:

>> find(ind) 

ans = 

    1 
    2 

>> ind 

ind = 

    3×1 logical array 

    1 
    1 
    0 

既然你想要的實際行指數,你可以在此之上使用find

要驗證,我們在您的評論中使用第二個示例:

>> A = [1 2;3 5;4 0]; 
>> x = [1 2 3]; 
>> ind = all(ismember(A, x) | ~A, 2) 

ind = 

    3×1 logical array 

    1 
    0 
    0 

>> find(ind) 

ans = 

    1 
+0

我認爲這只是輸出A的第一行,而不是行索引1和2. – jonem

+0

@jonem你想要行索引嗎?好的,讓我修改。 – rayryeng

+0

是的,這就是我遇到困難的地方,因爲由於元素(2,2)中的零元素,全部函數爲第2行返回零,即使我不想包含(2,2)元素在比較中。 – jonem

3

我認爲返工ismember的最好方法是通過檢查A中的非零元素來確保沒有「沒有成員」。012farrayfun可以快速完成工作。它爲您的特定機器使用最高效的並行計算。以下行應返回正確的輸出:

find(arrayfun(@(a) sum(~ismember(A(a,A(a,:)>0),x)),1:size(A,1))==0) 

這是你在找什麼? (1:floor(size(A,1)/ 2),floor(size(A,1)/ 2),這樣就可以將arrayfun操作分解爲幾部分):尺寸(A,1)或更小的塊),因爲MATLAB把一堆工人做任務,並且可以使用所有可用的RAM內存...

+0

感謝您的回答,您知道這與效率方面的for循環相比如何? – jonem

+0

我認爲它與具有最佳配置的parfor循環相比。效率取決於您的特定機器的並行容量...您可以使用該版本的cputime進行快速測試,並且for循環(for 1:size(A,1),並且總和(blabla)進入內部) 。 – ana

+0

由於您最初正確回答了問題,因此請您投票。我必須重做它3次才能正確:P – rayryeng