如果 M 是 logical ,那么矩阵乘法会因为必须在矩阵乘法之前将其转换为数字类型而受到影响,而其他两个则有一点性能提升 .
这是我使用的测试代码 .
sizes = round(linspace(100, 100000, 100));
times = zeros(numel(sizes), 3);
for k = 1:numel(sizes)
M = generateM(sizes(k));
times(k,1) = timeit(@()M * (1:size(M, 2)).');
M = generateM(sizes(k));
times(k,2) = timeit(@()max(M, [], 2), 2);
M = generateM(sizes(k));
times(k,3) = timeit(@()find(M.'), 2);
end
figure
plot(range, times / 1000);
legend({'Multiplication', 'Max', 'Find'})
xlabel('Number of rows in M')
ylabel('Execution Time (ms)')
function M = generateM(nRows)
M = zeros(nRows, 3);
col = randi([1 size(M, 2)], 1, size(M, 1));
M(sub2ind(size(M), 1:numel(col), col)) = 1;
end
2
您也可以滥用find并观察 M 的转置的 row 位置 . 您必须首先转置矩阵,因为 find 按列主要顺序运行:
3 回答
你可以用简单的矩阵乘法来解决这个问题 .
这通过将M x 3矩阵与3 x 1阵列相乘来实现,其中3x1的元素仅为
[1; 2; 3]
. 简而言之,对于M
的每一行,使用3 x 1阵列执行逐元素乘法 . 只有M
行中的1将在结果中产生任何结果 . 然后将该元素乘法的结果相加 . 因为每行只有一个"1",所以结果将是该1所在的列索引 .例如,对于
M
的第一行 .Update
基于@reyryeng和@Luis提供的解决方案,我决定运行一个比较,看看各种方法的性能如何比较 .
为了设置测试矩阵(
M
),我创建了一个原始问题中指定形式的矩阵,并改变了行数 . 使用randi([1 nCols], size(M, 1))
随机选择哪一列具有1 . 使用timeit
分析执行时间 .当使用
M
(MATLAB的默认值)M
运行时,您将获得以下执行时间 .如果
M
是logical
,那么矩阵乘法会因为必须在矩阵乘法之前将其转换为数字类型而受到影响,而其他两个则有一点性能提升 .这是我使用的测试代码 .
您也可以滥用find并观察
M
的转置的 row 位置 . 您必须首先转置矩阵,因为find
按列主要顺序运行:不确定这是否比矩阵乘法更快 .
另一种方法:使用max的第二个输出:
或者,如@rayryeng所示,沿第二维使用
max
而不是转置M
:对于
这给了
如果
M
在给定行中包含多个1
,则这将给出第一个1
的索引 .