我在问自己,用于查找矩阵的第一个非零列的值的最“矢量化”解决方案是什么样的。如果存在矢量化解决方案但非常丑陋/黑客,我也要求最优雅的解决方案。
假设我们有一个矩阵M
,我们可以假设它包含至少一个非零值:
M =
0 0 1 0 0
0 0 2 0 0
0 0 3 0 42
0 0 4 0 0
0 0 0 0 0
我希望找到第一列中不是全零的值;因此,对于此示例,所需的输出将是:
column =
1
2
3
4
0
我的第一次尝试使用for
循环并且工作正常,但可能没有充分利用matlab中提供的工具。
>> for i = 1:size(M,2)
col = M(:,i);
if find(col) % empty array evaluates to false
break;
end
end
>> col
col =
1
2
3
4
0
我提出的另一个解决方案是使用嵌套的find
和cellfun
调用,但它可能仍然不是解决问题的最佳方法。
>> C = find(cellfun(@isempty, cellfun(@find, num2cell(M,1), 'UniformOutput', 0)) == 0)
C =
3 5
>> M(:,C(1))
ans =
1
2
3
4
0
答案 0 :(得分:4)
这是一种方法,我会留给你测量性能改进(如果你对此感兴趣) -
M(:,find(any(M),1))
我建议您查看 Logical Operation in MATLAB
和logical indexing
,因为它们在索引方面非常方便。这些应该对你有用。
答案 1 :(得分:2)
当你要求'矢量化'解决方案时,由于逻辑索引,这个解决方案应该运行得更快:
tic; M(:,sum(M)>0); toc
Elapsed time is 0.000020 seconds.
tic; M(:,find(any(M),1)); toc
Elapsed time is 0.000028 seconds.
(虽然这不是衡量执行时间的最准确方法)
更准确的方法是在更大的矩阵上使用timeit
进行衡量:
M=rand(1024);
f1= @() M(:,sum(M)>0);
f2= @() M(:,find(any(M),1));
t1=timeit(f1)
t2=timeit(f2)
t1 =
0.0070
t2 =
2.3288e-05