2017-02-20 182 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