何时使用数组以及何时使用单元格数组



在Matlab中,我试图将匿名函数放入数组中:

>> a=[@(k)0.1/(k+1)    @(k)0.1/(k+1)^0.501]
??? Error using ==> horzcat
Nonscalar arrays of function handles are not allowed; use cell arrays
instead.

所以我想知道数组和单元格数组中允许哪些元素?

例如,我知道在一个数组中,元素可以是数字或字符串。还有什么?

简而言之:单元数组是异构容器,正则数组是同构。这意味着在规则数组中,所有元素都是相同类型的,而在单元数组中,它们可以不同。您可以在这里阅读更多关于单元阵列的信息。

当:时使用单元格阵列

  • 数组中有不同的类型
  • 您不确定将来是否可以将其扩展到其他类型
  • 您正在处理具有继承模式的对象
  • 您使用的是字符串数组-几乎在任何情况下,都最好使用char(n,m)
  • 您有一个大数组,并且经常更新函数中的单个元素-由于Matlabs写时复制策略
  • 您正在使用函数句柄(正如@Pursuit所解释的)

当:时,首选正则数组

  • 所有元素都具有相同的类型
  • 您在一次类似于数学运算的操作中更新整个数组
  • 你想要类型安全
  • 将来不会更改数组的数据类型
  • 您正在使用数学矩阵
  • 您正在处理没有继承的对象

关于写时复制的更多解释:

将数组传递给函数时,将传递指针/引用。

function foo(x)
     disp(x);
end
x= [1 2 3 4 5];
foo(x); %No copy is done here! A pointer is passed.

但是,当您更改它(或它的一部分)时,就会创建一个副本。

function foo(x)
    x(4) = x(4) + 1;
end
x= [1 2 3 4 5];
foo(x); %x is being copied! At least twice memory amount is needed.

在单元阵列中,仅复制单元。

function foo(x)
   x{4} = x{4} + 1;
end
x= {1 2 3 4 5}; %Only x{4} will be copied

因此,如果您调用一个函数来更改大型数组中的单个元素,则会产生大量副本,这会使其速度变慢。但在细胞阵列中,情况并非如此。

函数句柄实际上是这里的例外,原因是如果允许函数句柄成为非单元数组的一部分,Matlab语法会变得令人惊讶。例如

a = @(x)x+1;
a(2);  %This returns 2

但是,如果支持函数句柄数组,那么

b = [@(x)x+1,  @(x)x+2];
b(2);                  %This would return @(x)x+2
b(3) = @(x)x+3;        %This would extend the size of the array

那么这是允许的吗?

a(2) = @(x)x+2;       %Would this extend the size of the previously scalar array

长时间编辑:这在R14的发行说明中有记载,R14是第一个允许匿名函数的发行版。在R14之前,您可以创建函数句柄作为m文件函数的引用,并且它们可以放置在非单元数组中。这些只能使用feval(例如:fnSin = @sin; output = feval(fnSin, pi))来调用。

当引入匿名函数时,Mathworks更新了语法,以允许更简单的调用约定(例如fnSin = @sin; output = fnSin(pi)),这在使用函数句柄的非单元数组时会导致歧义。看起来他们已经尽了最大努力来宣传这种新行为,但那些被宣传的条件肯定已经过期了(这是2004年)。

数组只能存储固定长度的数据。例如,double、single、char、logic、integer。原因是(我想)它们直接存储在一个内存块中。另一方面,单元格存储为指针列表,每个指针可以指向不同大小的数据。

这就是数组不能存储字符串、函数句柄、数组和多种数据类型的原因。这些类型可以有不同的长度。例如,'bla'有3个字节,'blabla'有6个字节。因此,如果它们存储在同一个内存块中,如果您想将"bla"更改为"blabla",则必须移动内存的所有其余部分,这将非常缓慢,因此无法处理。

最新更新