2017-03-08 118 views
2

我有一个函数将一个矢量作为输入,使用另一个函数从输入创建一个导数矢量,然后比较两个矢量以产生其输出矢量。我现在有这一个工作循环如下:执行数组运算时不会循环涉及2个矢量的函数

function [parentIndexVec] = computeParentIndex(nameVec) 

    parentNameVec = computeParentName(nameVec); 
    for i=1:length(parentNameVec) 
     parentIndexVec(i) = find(strcmp(nameVec, parentNameVec{i})); 
    end 

end 

computeParentName功能基本返回nameVec副本连同其删除最后一个字母。循环前的单元阵列然后显示如下:

nameVec  = '' 'a' 'b' 'aa' 'ab' 'ba' 'aba' 'abb' 
parentNameVec = '' ''  ''  'a'  'a'  'b'  'ab'  'ab' 

该功能的目标是找到的,其中在parentNameVec每个元素出现在nameVec的索引,并且它的输出因此为如下:

parentIndexVec = 1  1  1  2  2  3  5  5 

我试图做一个cellfun来实现这一点,但无法让它运作,因为两个向量必须在每个点进行比较。

我的问题如下:

  1. 有没有办法消除的循环来做到这一点?
  2. 在大多数情况下,矩阵运算而不是循环是否真的更快?
  3. 如果是这样,那么cellfun在速度上与纯矩阵运算进行比较,还是会像循环一样慢?

感谢您的协助!

回答

1
  1. 您可以使用ismember内找到nameVec

    nameVec = {'' 'a' 'b' 'aa' 'ab' 'ba' 'aba' 'abb'}; 
    parentNameVec = {'' ''  ''  'a'  'a'  'b'  'ab'  'ab'}; 
    
    [~, parentIndexVec] = ismember(parentNameVec, nameVec) 
    % 1 1 1 2 2 3 5 5 
    
  2. 对于矩阵运算在parentNameVec串的出现,操作几乎可以肯定将是比for循环更快。两种方法之间的差异随着时间而减少,但仍然存在。不幸的是,在你的例子中,你正在使用没有矩阵操作的单元阵列。

  3. cellfun几乎总是慢于for循环,因为MATLAB的JIT编译器能够更好地优化for循环的内容。在更新版本的MATLAB(R2015b +)中尤其如此,其中执行引擎被重新设计并提供更好的加速度。

之所以这么说的,内置功能几乎总是要优于自己的实现算法(用于环路或其他方式),因为它已被Mathworks公司优化以获得不俗的表现,强大的错误检查功能,有时会在较低的级别上执行。

+0

我很欣赏这个回应。确切的我正在寻找的功能!所以,我实际上已经通过我的其他子函数来用'cellfun'替换'for'循环,所以我可能不知不觉地降低了它的效率。大多数使用'cellfun'完成的操作能以更快的矩阵操作方式完成吗?例如,上面提到的子函数('computeParentName')使用cellfun从'nameVec'单元格数组中删除每个元素的最后一个字母。有没有更简单的方法来做这样的事情? – teepee

+0

@teepee它真的取决于您要执行的操作的具体细节。对于内置于MATLAB中的字符串的单元阵列进行操作有很多操作。要删除最后一个字符,我会这样做:'regexprep(nameVec,'。$','')'只是用空字符串替换最后一个字符。 – Suever

+0

谢谢,我没有想过在MATLAB中使用正则表达式。非常好,他们可以处理chars和cellstr。这可以避免我写很多代码来处理这些区别。虽然我在这里,你会碰巧知道一个cellstr函数,它返回单元格数组中每个字符串的长度吗?即'lengthArray = foo({'aaa''bb''a'})'返回'[3 2 1]'? – teepee