单元阵列上的矢量化操作

时间:2011-06-27 21:44:42

标签: matlab vectorization

这篇文章是由following discussion触发的,关于单元格数组是否是“正常数组”,而且vectorizaton对单元格数组不起作用。

我想知道为什么在MATLAB中没有实现跟随矢量化语法,反对它的是什么:

>> {'hallo','matlab','world'} == 'matlab'
??? Undefined function or method 'eq' for input arguments of type 'cell'.

内部相当于

[{'hallo'},{'matlab'},{'world'}] == {'matlab'}

因为MATLAB知道何时投射,以下是作品:

[{'hallo','matlab'},'world']

单元格数组为an array of pointers。如果左侧和右侧都指向相同的对象,isequal('hallo','hallo')按预期返回true,那么为什么MATLAB仍然不允许最顶层的示例?

我知道我可以使用strmatchcellfun

概要

    上面示例中向量化所需的
  • 运算符==eq而不是isequal(其他运算符为<lt等。)
  • eq内置于数字类型,适用于所有其他类型(如字符串)MATLAB提供了对此(和其他)运算符进行重载的自由。
  • 因此,对于定义类型的单元格数组(如字符串),操作符向量化很有可能,但默认情况下不适用于任何类型。
  • 函数向量化(如myFun( myString )myFun( myCellOfStrings ))也是可能的,您只需在myFun内部实现它。函数sin(val)sin(array)也不是通过巫术工作,而是因为这两种情况都是在内部实现的。

4 个答案:

答案 0 :(得分:6)

首先,== isequal相同。使用==时调用的函数是eq,并且每个函数的范围都不同。

例如,在eq(A,B)中,如果B是标量,则函数检查 A的每个元素是否与B相等并且返回逻辑向量。

eq([2,5,4,2],2)

ans =

     1     0     0     1

但是,isequal(A,B)会检查所有方面A 是否等于B。换句话说,MATLAB无法区分AB之间的区别。为上述示例执行此操作:

isequal([2,5,4,2],2)

ans =

     0

我认为你真正打算在问题中提出的问题,但没有,是:

  

“为什么没有为单元格数组定义==?”

嗯,原因很简单:细胞不适合这种用途。当您开始考虑个别情况时,您可以很容易地看到如何为单元格实现这样的函数很快变得复杂。例如,考虑

{2,5,{4,2}}==2

您期望答案是什么?一个合理的猜测是

ans = {1,0,0}

这是公平的。但是,让我们说,我不同意。现在,我希望使用相等操作来遍历嵌套单元格并返回

ans = {1,0,{0,1}}

你能不同意这种解释吗?也许不是。它同样有效,在某些情况下,这就是你想要的行为。

这只是一个简单的例子。现在在单元格中添加嵌套单元格,不同类型等的混合,并考虑处理每个角落情况。对于开发人员来说,实现这样的功能很快就会变成一场噩梦,这些功能可以被所有人使用得令人满意。

因此,解决方案是重载函数,仅实现所需的特定功能,以便在您的应用程序中使用。 MATLAB提供了一种方法,通过创建@cell目录并定义eq.m,以便按照 想要的方式使用单元格。 Ramashalanka在his answer中证明了这一点。

答案 1 :(得分:4)

对于MATLAB来说,有许多事情对他们选择不这样做是很自然的。也许他们不想考虑许多特殊情况(见下文)。你可以通过重载自己完成。如果您创建目录@cell并将以下内容放在新函数eq.m中:

function c = eq(a,b)
if iscell(b) && ~iscell(a)
    c = eq(b,a);
else
    c = cell(size(a));
    for n = 1:numel(c)
        if iscell(a) && iscell(b)
            c{n} = isequal(a{n},b{n});
        else
            c{n} = isequal(a{n},b);
        end
    end
end

然后你可以做,例如:

>> {'hallo','matlab','world'} == 'matlab'
ans =     [0]    [1]    [0]

>> {'hallo','matlab','world'} == {'a','matlab','b'}
ans =     [0]    [1]    [0]

>> {'hallo','matlab','world'} == {'a','dd','matlab'}
ans =     [0]    [0]    [0]

>>  { 1, 2, 3 } == 2
ans =     [0]    [1]    [0]

但是,即使我在我的简单函数中考虑过几个案例,但我还没有考虑很多事情(检查单元大小相同,检查多元素单元格与单例等等)。

我使用isequal即使用eq调用它(即==),因为它更好地处理{'hallo','matlab','world'} == 'matlab',但实际上我应该考虑更多的情况。

(编辑:我的功能略短,但效率较低)

答案 2 :(得分:1)

这不是字符串所特有的。即使以下情况也不起作用:

{ 1, 2, 3 } == 2

单元格数组与“普通”数组相同:它们提供不同的语法,不同的语义,不同的功能,并且以不同的方式实现(一个额外的间接层)。

考虑单元数组上的==是否在isequal的基础上逐个元素地定义。所以,上面的例子没有问题。但是这个呢?

{ [1 0 1], [1 1 0] } == 1

在大多数情况下,由此产生的行为不会非常有用。那怎么样?

1 == { 1, 2, 3 }

你怎么定义这个? (我可以想到至少三种不同的解释。)

{ 1, 2, 3 } == { 4, 5, 6 }

那怎么样?

{ 1, 2, 3 } == { { 4, 5, 6 } }

还是这个?

{ 1, 2, 3 } == { 4; 5; 6 }

还是这个?

{ 1, 2, 3 } == { 4, 5 }

您可以添加各种特殊情况处理,但这会使语言更不一致,更复杂,更难以预测。

答案 3 :(得分:1)

出现此问题的原因是:单元格数组可以在不同的单元格中存储不同类型的变量。因此,无法为整个阵列很好地定义运算符==。一个细胞甚至可能包含另一个细胞,这进一步加剧了这个问题。

想想{4,'4',4.0,{4,4,4}} == '4'。应该是什么结果?每种类型都以不同的方式进行评估。