我有一个复杂的单元阵列,其中的列包含1d单元阵列或1d矩阵。在每一行中,单元格数组的维数与矩阵相同,但在行之间可能会有所不同。
玩具示例看起来像这样
ex = { [1:3], {{'cat', 'dog', 'bat'}};
[0:1], {{'abc', 'def'}} }
我还有一个逻辑矩阵的单元格数组,我想用它来掩盖ex
mask = {[false true false];
[true false]}
所需的输出是
after_mask = { [2], {{'dog'}};
[0], {{'abc'}} }
我知道如果我使用for循环,可以取消我的单元格数组值。
new_col2 = cell(size(ex,1), 1);
for idx=1:size(ex,1)
x = ex{idx, 2};
x = [x{:}]; % Un-nest
new_col2{idx, :} = x(mask{idx, 1});
end
但是for循环似乎不必要地混乱。我想要一个矢量化的解决方案。
编辑从我的第一个自我回答中删除:我也可以使用cellfun
。最初,我认为这将是一个矢量化的解决方案,但在发布后,Suever和rayryeng指出cellfun
没有按照bsxfun
的方式进行矢量化。
function [x]=unnestAndIndex(x,y)
x = [x{:}];
x = x(y);
end
new_col2 = cellfun(@unnestAndIndex, ex(:,2), mask, 'UniformOutput', false);
也可以嵌套cellfun
次调用,而不是声明一个额外的函数,但同样,cellfun
不是真正的矢量化
new_col2 = cellfun(@(x, y) ...
cellfun(@(x1) x1(y), x), ex(:,2), mask, 'UniformOutput', false);
是否有矢量化方式来索引我的嵌套单元格数组?
答案 0 :(得分:0)
在评论中,rayryeng说
cellfun是一个美化的for循环,带有额外的错误检查和褶边。 对于任何具有每种类型的非均匀细胞的处理, for循环是最好的选择,你最好写一个for循环 我们知道JIT最终会开始。
所以我决定在问题的例子上运行一个基准测试来测试for循环是否真的是最好的选择。
ex = { [1:3], {{'cat', 'dog', 'bat'}}; ...
[0:1], {{'abc', 'def'}} };
mask = {[false true false]; ...
[true false]};
display('1000 iterations with for loop');
tic;
for it = 1:1000
new_col2 = cell(size(ex,1), 1);
for idx=1:size(ex,1)
x = ex{idx, 2};
x = [x{:}]; % Un-nest
new_col2{idx, :} = x(mask{idx, 1});
end
end
toc;
display('1000 iterations with function call');
tic;
for it = 1:1000
new_col2 = cellfun(@unnestAndIndex, ex(:,2), mask, 'UniformOutput', false);
end
toc;
display('1000 iterations with nested cellfun annonymous function');
tic;
for it = 1:1000
new_col2 = cellfun(@(x, y) ...
cellfun(@(x1) x1(y), x), ex(:,2), mask, 'UniformOutput', false);
end
toc;
输出将方法从最快到最慢排列为
cellfun
函数调用:0.032181秒(比for循环慢2倍)cellfun
:0.201483秒(比for-loop慢10倍)For-loops win!我仍然有兴趣与矢量化解决方案进行比较(如果存在)。