我们可以用sortrows
作为首先对索引和相应值进行排序的预处理步骤,如其文档所述:
SORTROWS
uses a stable快速排序的版本。
作为下标subs
应该根据它们的线性索引进行排序,我们需要按逆字典顺序对它们进行排序。这可以通过在使用之前和之后翻转列顺序来实现sortrows
.
这为我们提供了以下稳定版本的代码accumarray
:
function A = accumarrayStable(subs, val, varargin)
[subs(:,end:-1:1), I] = sortrows(subs(:,end:-1:1));
A = accumarray(subs, val(I), varargin{:});
选择:
正如建议的路易斯·门多, 代替sortrows
还可以从下标生成线性索引并使用sort
反而。
function A = accumarrayStable(subs, val, varargin)
if numel(varargin)>0 && ~isempty(varargin{1})
sz = varargin{1};
else
sz = max(subs,[],1);
end
[~, I] = sort(subs*cumprod([1,sz(1:end-1)]).');
A = accumarray(subs(I,:), val(I), sz, varargin{:});
请注意,我们应该使用1+(subs-1)*cumprod([1,sz(1:end-1)]).'
用于转换为线性索引。我们省略了+1
and -1
作为结果sort
仍然会是一样的;这节省了我们几个周期。
上述解决方案中哪一种更快取决于您的机器和 MATLAB 版本。例如,您可以通过以下方式进行测试:
A = randi(10, 1e4, 5);
timeit(@()accumarrayStable(A(:,1:end-1), A(:,end), [], @(x)x(1))