单元数组

单元数组是一种特殊的数组,这种数组的元素是单元,能包含其他MATLAB数组。例如,单元数组的其中一个单元可能包含一个实型矩阵;另一个单元又包含文本字符串数组;而第三个单元又包含值为复数的矢量,可以生成任意大小和形状的单元数组。结构和单元数组为不同类型的数据提供了一种系统存储机制。它们主要在组织数据的方式上有所不同:在结构中,从命名字段访问数据;在单元数组中,通过矩阵索引操作访问数据。[大谦MATLAB,dqmatlab点com]

创建单元数组

可以通过下面的方式创建单元数组。

1.通过赋值语句创建单元数组

通过给单个单元赋值来生成单元数组,每次给一个单元赋值,根据赋值的情况,自动生成一定大小的数组。给单元赋值有以下两种方式。

单元索引:按标准数组方式把单元索引号放到小括号中间,把单元的内容放在赋值语句的右端,用大括号括起来。

【例2-79】创建一个22的单元数组A:

code.matlab
A(1,1) = {[1 4 3; 0 5 8; 7 2 9]};
A(1,2) = {'Liu zhong'};
A(2,1) = {3+7i};
A(2,2) = {-pi:pi/10:pi};

注意:“{ }”表示一个空的单元数组,就像“[ ]”表示空的数值数组矩阵一样。可以在任何单元数组赋值时使用空的单元数组。

内容索引:以标准数组标注方式把单元索引号以大括号括起来放在左侧,在赋值语句的右侧指定单元内容。

code.matlab
A{1,1} = [1 4 3; 0 5 8; 7 2 9];
A{1,2} = 'Liu zhong';
A{2,1} = 3+7i;
A{2,2} = -pi:pi/10:pi;

注意:如果已经有一个给定名称的数值数组,则不要在没有清除数值数组的情况下试图创建一个同名的单元数组。因为在没有清除数值数组的情况下,MATLAB会认为你混淆了单元和数值的语法,会生成一个错误。

MATLAB以压缩的形式显示单元数组:

code.matlab
A =
         [3x3 double]    'Liu zhong'
    [3.0000+ 7.0000i]    [1x21 double]

要显示单元的全部内容,可以使用celldisp函数。对于单元结构的高级图形显示,可以使用cellplot函数。如果给一个维数大于当前数组维数的单元赋值,则MATLAB会自动扩展数组,以包含指定的索引号它会用空矩阵填充所有间隔的单元。如下面的赋值将一个22的单元数组A放到一个33的单元数组中。

code.matlab
A(3,3) = {5};

2.用cell函数预分配单元数组

使用cell函数,可以预分配指定大小的空单元数组。下面的语句可以创建一个空的单元数组:

code.matlab
B = cell(2,3);

下面用赋值语句填充B单元:

code.matlab
B(1,3) = {1:3};

从单元数组中获取数据

可以从单元数组中获取数据,或者以标准数组或单元数组的形式保存结果。本节介绍:

用内容索引获取单元内容;

用单元索引获取单元子集。

1.用内容索引获取单元内容

可以用语句右端的内容索引获取单个单元中的某些或全部数据。在赋值语句的左侧指定一个变量,可以获取单元中的内容。用大括号把语句右端的单元索引表达式括起来。

【例2-80】

对于下面的单元数组N:

code.matlab
N{1,1} = [1 2; 4 5];
N{1,2} = 'Name';
N{2,1} = 2-4i;
N{2,2} = 7;

可用c=N{1,2}获取N{1,2}中的字符串,即

code.matlab
c = N{1,2}
c =
   Name

注意:在赋值时,可以使用内容索引获取单个单元中的内容,而不是单元子集中的内容。例如,语句A{1,:} = value 和B = A{1,:}都是不合法的。但是,可以在逗号间隔变量列表中的任何地方使用单元子集。

2.用单元索引获取单元子集

使用单元索引可以把全部单元集赋给另一个变量,创建一个新的单元数组。使用colon运算符可以获取单元数组中的单元子集。

删除单元和重塑单元数组

可以用单条语句删除单元的整个维,就像删除标准数组一样。在删除单元的行或列时可以使用矢量索引号。将空矩阵赋给该维。例如:

code.matlab
A(2)=[]

在删除单元时,大括号不出现在赋值语句中。

可以用reshape函数重塑单元数组。单元个数必须与重塑以后的相同,不能使用reshape函数添加或删除单元。

【例2-81】

下面的命令行首先创建了一个单元数组A,然后利用reshape函数改变它的大小。

code.matlab
A = cell(3,4);
size(A)
ans =
    3     4
B = reshape(A,6,2);
size(B)
ans =
    6     2

采用函数和运算符

使用索引,可以将函数和运算符应用于单元内容中。

【例2-82】使用内容索引调用一个以单元内容为参数的函数。

code.matlab
A{1,1} = [1 2; 3 4];
A{1,2} = randn(3,3);
A{1,3} = 1:5;
B = sum(A{1,1})
B =
     4     6

要将函数应用到多个非嵌套单元数组的单元中,可使用循环结构。例如:

code.matlab
for k = 1:length(A)
    M{k} = sum(A{1,k});
end

单元数组嵌套

单元数组的单元可以包含另一个单元数组,或者以单元数组为元素的数组。在cell函数中可以使用嵌套的大括号或者赋值语句创建嵌套的单元数组。然后可以获取和操作单个的单元、单元子数组或单元元素。

1.用嵌套的大括号创建嵌套数组

【例2-83】可以通过成对的大括号来创建一个嵌套的单元数组。

在命令窗口中输入:

code.matlab
clear A
A(1,1) = {magic(5)};
A(1,2) = {{[5 2 8; 7 3 0; 6 7 3] 'Test 1'; [2-4i 5+7i] {17 []}}}
A =
    [5x5 double]    {2x2 cell}

注意:语句的右端被两对大括号括起来,第一对表示单元数组A的单元(1,2),第二对在外部单元中包括一个单元数组。

2.用cell函数生成嵌套数组

用cell函数嵌套单元数据,将单元的输出值赋给一个已经存在的单元。

【例2-84】创建一个空的单元数组:A=cell(1,2);在A(1,2)中创建一个单元数组:A(1,2)={cell(2,2)};通过赋值来填充A。

code.matlab
A(1,1) = {magic(5)};
A{1,2}(1,1) = {[5 2 8; 7 3 0; 6 7 3]};
A{1,2}(1,2) = {'Test 1'};
A{1,2}(2,1) = {[2-4i 5+7i]};
A{1,2}(2,2) = {cell(1,2)};
A{1,2}{2,2}(1) = {17};

第一套索引号获取顶层单元,后面依次获取更深层单元的数据。例如:数组A有3层嵌套,要获取单元(1,1)中的数值,使用A{1,1};要获取单元(1,2)中位置(1,1)处的数组,使用A{1,2}.{1,1};要获取单元(1,2)中的数组,使用A{1,2};要获取单元(1,2)中位置(2,2)处的空单元,使用A{1,2}.{2,2}.{1,2}。

单元数组与数值数组之间的转换

使用循环可以在单元和数值数组之间进行转换。

【例2-85】创建一个单元数组F如下:

code.matlab
F{1,1} = [1 2; 3 4];
F{1,2} = [-1 0; 0 1];
F{2,1} = [7 8; 4 1];
F{2,2} = [4i 3+2i; 1-8i 5];

现在使用3套循环,将下面的内容复制到数值数组NUM中。

code.matlab
for k = 1:4
   for m = 1:2
      for n = 1:2
         NUM(m,n,k) = F{k}(m,n);
      end
   end
end

类似地,必须使用循环将数值数组中的每个值赋给单元数组中的单元。

code.matlab
G = cell(1,16);
for m = 1:16
   G{m} = NUM(m);
End

字符串单元数组

把多组字符串保存为单元数组的形式,可以避免在短字符串后面频繁地添加空格。利用MATLAB提供的一系列函数,可以针对字符串单元数组进行两种操作:一种是在标准字符数组与字符串单元数组之间进行转换操作,另一种是对字符串单元数组进行字符串比较操作。

【例2-86】cellstr函数可以把字符串转换到一个字符串单元数组中。

对于字符串

code.matlab
data = ['Sun junfang';'NewStudent';'Beijing   '];

该矩阵通过空格补齐使各行的长度相同。

现在使用cellstr函数创建单元的列矢量,每个单元包含data数组中的一个字符串。

code.matlab
celldata = cellstr(data)
celldata =
    'Sun junfang'
    'NewStudent'
    'Beijing'

注意:cellstr函数把各行中为了补齐所添加的空格去掉了。例如:

code.matlab
length(celldata{3})
ans =
    7

iscellstr函数确定输入变量是否为字符串单元数组。它返回一个逻辑值true(1)或false(0)。

code.matlab
iscellstr(celldata)
ans =
     1

结构单元数组

【例2-87】使用单元数组来保存具有不同字段的多组结构。

创建结构单元数组c_str。

code.matlab
c_str = cell(1,2);
c_str{1}.label = ' - 12/5/94';
c_str{1}.obs = [47 52 55 48; 17 22 35 11];
c_str{2}.xdata = [-0.03 0.41 1.98 2.12 17.11];
c_str{2}.ydata = [-3 5 18 0 9];
c_str{2}.zdata = [0.6 0.8 1 2.2 3.4];

c_str数组的单元1包含一个有两个字段的结构,一个为字符串,另一个为矢量。单元2包含一个有3个矢量字段的结构。在创建结构的单元数组时,必须使用内容索引。同样,必须使用内容索引来获取单元中结构的内容。内容索引的语法为:

code.matlab
cell_array{index}.field

例如,要获取单元1中结构的label字段,使用c_str{1}.label。

多维单元数组

与数值数组相似,多维单元数组是二维单元数组模型的扩展。可以用cat函数生成多维单元数组。

【例2-88】创建一个简单的三维单元数组C。

code.matlab
A{1,1} = [1 2;4 5];
A{1,2} = 'Name';
A{2,1} = 2-4i;
A{2,2} = 7;
B{1,1} = 'Name2';
B{1,2} = 3;
B{2,1} = 0:1:3;
B{2,2} = [4 5]';
C = cat(3,A,B);