我有矩阵
p=[1 2 3 4;
5 6 7 8;
10 20 30 50];
我想计算列 iMin 和 iMax 之间的每行元素的总和,每行的 iMin 和 iMax 都不同
例如对于
iMin = [3 2 1];
iMax = [4 4 3];
结果是
[7 21 60]
有没有一种简单的 Octave / Matlab 方法可以在没有循环的情况下做到这一点?
您可以使用逻辑索引来实现这一点,遵循与我对您的其他问题的回答类似的方法。
假设iMin
并且iMax
具有与行数相同的条目数,p
您可以水平平铺p
ie的列索引,[1:size(p,2)]
并将其与垂直平铺进行比较,iMin
并为满足您的标准的条目iMax
生成逻辑索引,因此:p
c_min=repmat(iMin',1,size(p,2))
c_max=repmat(iMax',1,size(p,2))
c_ind=repmat([1:size(p,2)],size(p,1),1)
result=sum(p.*(c_ind>=c_min & c_ind<=c_max),2)
给予:
result =
7
21
60
没有循环:-)
我知道我有点晚了,但这是我的贡献:
单线bsxfun
:
sum((p.*bsxfun(@le,iMin(:),1:size(p,2)).*bsxfun(@ge,iMax(:),1:size(p,2))).')
一个解决方案linear indexing
:
aux = [zeros(1,size(p,1)); cumsum(p.')];
rowjumps = 0:size(p,2)+1:numel(p);
result = aux(iMax+1+rowjumps) - aux(iMin+rowjumps);
我相当确定
[nRows,nCols]=size(p);
result = zeros(nRows,1);
for iRow = 1:nRow
result(iRow) = sum(p(iRow,iMin(iRow):iMax(iRow));
end
是最快的解决方案,至少在最新版本的 Matlab 上是这样。
要一次性执行求和,您需要创建一个包含 1 和 0 的数组来进行 mask p
,即
[nRows,nCols] = size(p);
idxCells = arrayfun(@(x,y)...
[false(1, x-1), true(1,y-x+1), false(1,nCols-y)], iMin, iMax,...
'UniformOutput',false);
result = sum( p .* cell2mat(idxCells), 2)