【发布时间】:2013-03-23 15:21:50
【问题描述】:
我有一个索引数组 I 和值 X,并且想要创建一个元胞数组 C,因此 C{i} = X(I==i)。计算 C 的最快和最佳方法是什么?
最直接的方法是为 I 中的所有唯一 i 评估 C{i} = X(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 秒
【问题讨论】:
-
请注意,为了更好地比较速度,您应该将
C预先分配为C = cell(max(indices),1); -
是的,我确实这样做了,但为了清楚起见,将其省略了。在这些情况下,它对运行时间没有显着影响。
标签: matlab