我可以矢量化逻辑索引来访问嵌套的单元格数组吗?

时间:2017-02-17 00:16:15

标签: matlab vectorization

我有一个复杂的单元阵列,其中的列包含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);

是否有矢量化方式来索引我的嵌套单元格数组?

1 个答案:

答案 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;

输出将方法从最快到最慢排列为

  1. For loop:0.016249秒
  2. cellfun函数调用:0.032181秒(比for循环慢2倍)
  3. 嵌套cellfun:0.201483秒(比for-loop慢10倍)
  4. For-loops win!我仍然有兴趣与矢量化解决方案进行比较(如果存在)。