仅比较非零元素

时间:2017-02-20 23:16:38

标签: matlab

我想要实现的具体任务很难描述,所以这里有一个例子:给定A和x

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

x = [1 2 3];

我希望算法输出

output: [1 2]

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

我使用单元格数组和循环完成了这项工作;然而,A和x非常大,我的方法根本没有效率。此外,我似乎无法弄清楚如何返工ismember给我我想要的。什么是最快/最少内存密集型方法?

编辑:道歉,我原来的例子太简单了。现在已经纠正了。

2 个答案:

答案 0 :(得分:4)

第一个答案很好,但我建议使用List<Integer> unavTimesConv = new ArrayList<Integer>(); List<String> unavDays = new ArrayList<String>(); String[] unavDaysTemp = request.getParameterValues("days"); if(request.getParameterValues("days") != null) { for(int i = 0; i < (unavTimesConv.size() / 2); i++) { for(int j = (7*i); j < (7*(i+1)); j++) { if(unavDaysTemp[j].equals("M")) { unavDays.add("M"); } else if(unavDaysTemp[j].equals("T")) { for(int k = 0; k < 1; k++) {unavDays.add(null);} unavDays.add("T"); } else if(unavDaysTemp[j].equals("W")) { for(int k = 0; k < 2; k++) {unavDays.add(null);} unavDays.add("W"); } else if(unavDaysTemp[j].equals("TH")) { for(int k = 0; k < 3; k++) {unavDays.add(null);} unavDays.add("TH"); } else if(unavDaysTemp[j].equals("F")) { for(int k = 0; k < 4; k++) {unavDays.add(null);} unavDays.add("F"); } else if(unavDaysTemp[j].equals("S")) { for(int k = 0; k < 5; k++) {unavDays.add(null);} unavDays.add("S"); } else {unavDays.add("Something busted");} } } } 。有更多雄辩的方法可以做你所要求的。将ismemberall结合使用,然后在完成后将矩阵arrayfun编入索引。基本上,您的问题是确定行是否具有A中找到的所有值并忽略零值。在这种情况下,我们可以找到矩阵x中实际为零的所有值,然后使用它来增加我们的结果。

使用A作为第一个输入,A作为第二个输入,将返回与x大小相同的矩阵,告诉您A中的元素是否为Ax中找到。如果您想检查A中是否可以找到某行的矩阵x中的所有元素,请检查行中所有元素是否为1。除此之外,找到所有零的元素,然后使用ismember的输出将这些设置为1.这可以使用logical OR来完成。之后,您可以使用all并使用ismember的输出作为all的第一个输入并将第二个参数设置为2来独立检查每一行。这将返回所有矩阵A中的行,x 忽略 A中{0}}行的任何值为零的任何列寻找:

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将是:

>> ind

ind =

  3×1 logical array

   1
   1
   0

由于您需要实际的行索引,因此您可以在此基础上使用find

>> find(ind)

ans =

     1
     2

要验证,请在评论中使用您的第二个示例:

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

答案 1 :(得分:3)

我认为返工的最佳方式是成员是通过检查A中的非零元素来确保没有“没有成员”。 arrayfun可以快速完成工作。它为您的特定机器使用最有效的并行计算。以下行应返回正确的输出:

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

这是你在找什么?

但是,如果您的问题与内存有关,那么您可能必须将arrayfun操作分解为多个部分(1:floor(size(A,1)/ 2),floor(size(A,1)/ 2) :size(A,1)或更小的块),因为MATLAB让一大堆工作人员完成任务,并且可以使用你所有可用的RAM内存......