什么是通过索引对值进行分组的快速方法?

时间:2013-03-23 15:21:50

标签: matlab

我有一个索引数组I和值X,并希望生成一个单元格数组C,以便C {i} = X(I == i)。什么是计算C的最快和最好的方法?

最直接的方法是评估C{i} = X(I==i)我所有的独特i(方法1):

for i = unique(I)
    C{i} = X(I == i);
end

另一种天真的方法是循环遍历I中的所有i并将相应的x追加到C(方法2):

C = cellfun(@(x)(zeros(1,0)),cell(1,max(indices)),'UniformOutput',false);
for j = 1:length(I)
    i = I(j);
    C{i} = cat(2,C{i},X(j));
end

这两种方法都不是很快。要进行基准测试,让我们生成一些测试数据:

I = floor(rand(1,N)*M)+1;
X = rand(1,N);

使用N = 1000000, M = 1000这两种方法:

  • 方法1:4.79秒
  • 方法2:11.1秒

这里,方法1最好(仍然很慢)。将问题的参数更改为N = 1000000, M = 10000会显着改变:

  • 方法1:48.5秒
  • 方法2:10.3秒

基本上,这两种方法都是数量级太慢。评估C的最佳方法是什么?

编辑:正确的答案显然是Jonas的下方。我附上基准测试结果供参考。与上述方法相比,C中元素的顺序不同。除此之外,以下内容给出相同的输出:

C = accumarray(I',X,[],@(x){x'})';
  • N = 100000, M = 1000:0.0397秒
  • N = 100000, M = 10000:0.145秒

1 个答案:

答案 0 :(得分:5)

最快的写作方式(也可能是最快的方式)是accumarray

C = accumarray(I,X,[],@(x){x});