好的,我做了一些测试,我认为引用中的“排序”是指线性索引意义上的。(如果重要的话,我在 R2013a 上)
为了理解如何accumarray
调用指定的函数,我将通过指定要应用的函数来使用将值分组到单元数组中的技巧。fun = @(x) {x}
1) 一维索引
首先让我们创建一些下标和值
N = 10; sz = 4;
subs = randi([1 sz], [N 1]);
vals = (1:N)'*100;
现在我们在未排序的索引上调用 ACCUMARRAY(多次)
C = cell(5,1);
for i=1:5
C{i} = accumarray(subs, vals, [], @(x){x});
end
传递给函数的值的顺序是任意的,但在多次运行中仍然是一致的:
>> assert(isequal(C{:}))
>> celldisp(C{1})
ans{1} =
800
900
700
ans{2} =
300
ans{3} =
1000
200
100
ans{4} =
400
600
500
这就是文档警告您fun
不应依赖于传递给它的值的顺序的原因。
现在,如果我们预先对下标进行排序:
[~,ord] = sort(subs);
C = cell(5,1);
for i=1:5
C{i} = accumarray(subs(ord), vals(ord), [], @(x){x});
end
assert(isequal(C{:}))
celldisp(C{1})
我们将看到这些值被传递给自己排序的函数:
ans{1} =
700
800
900
ans{2} =
300
ans{3} =
100
200
1000
ans{4} =
400
500
600
2) 二维索引
在 2D 下标索引的情况下,我尝试过同样的事情。首先我们从随机数据开始:
%# some 2d subscripts and corresponding values
N = 10; sz = 2;
subs = randi([1 sz], [N 2]);
vals = (1:N)*100;
以下是未排序索引的情况:
C = cell(5,1);
for i=1:5
C{i} = accumarray(subs, vals, [], @(x){x});
end
assert(isequal(C{:}))
celldisp(C{1})
这是我尝试“按行排序”的时候:
[~,ord] = sortrows(subs, [1 2]);
C = cell(5,1);
for i=1:5
C{i} = accumarray(subs(ord,:), vals(ord), [], @(x){x});
end
assert(isequal(C{:}))
celldisp(C{1})
最后是我们按“线性索引”排序的时候:
[~,ord] = sort(sub2ind([sz sz], subs(:,1), subs(:,2)));
C = cell(5,1);
for i=1:5
C{i} = accumarray(subs(ord,:), vals(ord), [], @(x){x});
end
assert(isequal(C{:}))
celldisp(C{1})
我将省略长输出,并报告仅在最后一种情况下将值传递给函数ordered。所以我得出结论,“排序”标准是基于线性索引的。
ans{1,1} =
[]
ans{2,1} =
200
600
700
ans{1,2} =
100
300
400
500
1000
ans{2,2} =
800
900
奖金:
尝试改用以下函数:
function out = fun(x)
out = {x};
disp('[')
disp(x)
disp(']')
end
您会看到该函数以不可预知的方式被调用,即使有一些重复!您可能必须增加数据的大小才能看到这种行为......
就向后兼容性而言,文档在 MATLAB R14sp3中一直提到这个注释,但没有提到 R14sp2。鉴于它自2005 年以来已被记录在案,我会说依赖此功能是安全的(我怀疑任何使用此类旧版本的人都希望新代码能够正常工作!)