4

我有一个索引数组 I 和值 X,并且想要创建一个元胞数组 C,因此 C{i} = X(I==i)。计算 C 的最快和最好的方法是什么?

最直接的方法是评估C{i} = X(I==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这两种方法:

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

在这里,方法 1 是最好的(仍然很慢)。更改问题的参数以N = 1000000, M = 10000显着改变事情:

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

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

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

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

1 回答 1

5

最快的编写方式(并且很可能是最快的运行方式)是accumarray

C = accumarray(I,X,[],@(x){x});
于 2013-03-23T15:24:43.213 回答