这个问题的另一个答案!这次,我们将比较以下 4 种方法的性能:
- 我原来的方法
- EitanT 的原始方法(不处理 emtpies)
- EitanT 使用字符串的改进方法
- 一种新方法:一个简单的 for 循环
- 另一种新方法:矢量化、空安全版本
测试代码:
% Set up test
N = 1e5;
S(N).b = [];
for ii = 1:N
S(ii).b = randi(6); end
% Rody Oldenhuis 1
tic
sol1 = find( cellfun(@(x)isequal(x,6),{S.b}) );
toc
% EitanT 1
tic
sol2 = find([S.b] == 6);
toc
% EitanT 2
tic
str = sprintf('%f,', S.b);
values = textscan(str, '%f', 'delimiter', ',', 'EmptyValue', NaN);
sol3 = find(values{:} == 6);
toc
% Rody Oldenhuis 2
tic
ids = false(N,1);
for ii = 1:N
ids(ii) = isequal(S(ii).b, 6);
end
sol4 = find(ids);
toc
% Rody Oldenhuis 3
tic
idx = false(size(S));
SS = {S.b};
inds = ~cellfun('isempty', SS);
idx(inds) = [SS{inds}]==6;
sol5 = find(idx);
toc
% make sure they are all equal
all(sol1(:)==sol2(:))
all(sol1(:)==sol3(:))
all(sol1(:)==sol4(:))
all(sol1(:)==sol5(:))
我的机器上的工作结果(AMD A6-3650 APU(4 核),4GB RAM,Windows 7 64 位):
Elapsed time is 28.990076 seconds. % Rody Oldenhuis 1 (cellfun)
Elapsed time is 0.119165 seconds. % EitanT 1 (no empties)
Elapsed time is 22.430720 seconds. % EitanT 2 (string manipulation)
Elapsed time is 0.706631 seconds. % Rody Oldenhuis 2 (loop)
Elapsed time is 0.207165 seconds. % Rody Oldenhuis 3 (vectorized)
ans =
1
ans =
1
ans =
1
ans =
1
在我的 Homebox(AMD Phenom(tm) II X6 1100T(6 核),16GB RAM,Ubuntu64 12.10)上:
Elapsed time is 0.572098 seconds. % cellfun
Elapsed time is 0.119557 seconds. % no emtpties
Elapsed time is 0.220903 seconds. % string manipulation
Elapsed time is 0.107345 seconds. % loop
Elapsed time is 0.180842 seconds. % cellfun-with-string
一定会喜欢那个 JIT :)
哇……有人知道为什么这两个系统的行为如此不同吗?
此外,鲜为人知的事实 -cellfun
使用可能的字符串参数之一非常快(这表明匿名函数需要多少开销......)。
不过,如果您可以绝对确定没有空,请选择 EitanT 的原始答案;这就是 Matlab 的用途。如果你不能确定,就去循环。