1. 前言
Matlab单元数组(cell)和结构体(structure)都可以将不同类型的相关数据集成到一个单一的变量中,使得大量的相关数据的处理变得非常简单而且方便。但是,需要注意的是,单元数组和结构体只是承载其他数据类型的容器,大部分的数学运算是针对两者之中具体的数据进行,而不是针对单元数组或结构体本身进行。
单元数组中的每一个单元是通过一个数字来进行索引的,但用户需要加入到一个单元中或者从一个单元提取数据时,需要给出单元数组中该单元的索引。结构体和单元数组十分相似,两者的区别在于,结构体中的数据存储并不是由数字来标示,而是通过结构体中的名称来进行标示的。
2. 单元数组的创建和操作
单元数组中的每一个元素称为单元(cell),单元中可以包含任何类型的Matlab数据,即可以是数组,字符,符号对象,单元数组或结构体等。理论上,单元数组可以创建任意数的单元数组,大多数情况下,为简单起见,创建简单的单元数组(如一维单元数组)。单元数组的创建方法可以分为两种,通过赋值语句直接创建;或通过cell函数首先为单元数组分配内存空间,然后再对每个单元赋值。
直接通过赋值语句创建单元数组时,可以采用两种方法来进行,即按单元索引法和内容索引法。按单元索引法赋值时,采用标准数组的赋值方法,赋值时赋给单元的数值通过花括号{}将单元内容括起来。按内容索引法赋值时,将花括号写在等号左边,即放在单元数组名称后。下面通过例子说明这两种赋值方法。
>>clear A % 保证赋值的单元数组名称不重名
>>%按单元索引法赋值
>>A(1,1)={[1 3 5;2 4 6; 1 4 7]};
>>A(1,2)={3+5i};
>>A(2,1)={'Tsinghua in Beijing'};
>>A(2,2)={0:pi/5:pi};
>>A
A= [3x3double] [3.0000+5.0000i]
'Tsinghua in Beijing' [1x6 double]
>> 按内容索引法赋值
>>B{1,1}=[1 2 3;4 5 6;7 8 9];
>>B{1,2}=2+3i;
>>B{2,1}='Beijing Univ';
>>B{2,2}=1:2:13;
>>B
B= [3x3double] [2.0000+3.0000i]
'Beijing Univ' [1x7double]
按单元索引法和按内容索引法所创建的单元是等效的。但需要注意的是,用花括号可以访问单元数组单元的内容,而圆括号则只用于表示单元数组的单元而不显示单元数组单元的内容。
>>B{2,2}
ans=
1 3 5 7 9 11 13
>>B(2,2)
ans=
[1x7 double]
>>A{2,:}
ans=
Tsinghua in Beijing
ans=
0 0.6283 1.2566 1.8850 2.5133 3.1416
单元数组创建的另一种方法是通过cell函数来进行创建。在创建时,可以采用cell函数生成空的单元数组,为单元数组分配内存,然后,再向单元数组内存储内容。
>>D=cell(2,3)
D=
[] [] []
[] [] []
>>D{1,1}=randperm(5)
D=
[1x5 double] [] []
[] [] []
3. 结构体创建
结构体(structure)和单元数组非常相似,也是将不同类型的数据集中在一个单独变量中,结构体通过字段(fields)来对元素进行索引,在访问时只需通过点号来访问数据变量,结构体可以通过两种方法进行创建,即通过直接赋值方式创建或通过struct函数来创建。
>>%直接赋值方法创建结构体
>>circle.radius=3.0;
>>circle.center=[0 0];
>>circle.color='red';
>>circle.linestyle='--'
circle=
radius:3
center:[0 0];
color:'red'
linestyle:'--'
>>%用struct函数创建
>>data1={3.0,5.0,'sqrt(7)'};
>>data2={[0 0][1 1][3 5]};
>>data3={'--''...''-.-'};
>>data4={'red''blue''yellow'};
>>data5={'yes''no''no'};
>>circle=struct('radius',data1,'center',data2,'linestyle',data3,'color',data4,'filled',data5)
circle=
1x3 struct array with fields:
radius
center
linestyle
color
filled
4. 使用场景举例
比如说,我做的这个课程设计。
一个用户设备有这些属性:(这仅仅只是一部分,没有列举完)
ID
level:UE等级
x
y
belongSBS_ID
minK
maxK
stillNeedRBnum
RBQTable = cell(0),RBQTable = RB Quality Table,每个元素是一个结构体,包括:RB_ID、RBquality
D:卸载任务量
C:卸载任务对应的CPU周期需求
这些属性,可以设计一个用户结构体,例如命名为:UE,把对应的属性封装在一起,很方便。比如说你这时候需要访问UE的第一个属性,那你只需要这样写代码:UE.ID,第二个属性则这样写代码:UE.level,依次类推。
如果用矩阵的话,可能得这样写:第一列存放所有用户设备的ID号,第二列存放用户等级,第三列存放…,第四列存放…,…。这样做很麻烦。
封装成结构体之后,定义一个cell类型的数组,例如命名为:allUE,每一个元素存放用户结构体。效果是这样:{ 第一个用户结构体,第二个用户结构体,第三个用户结构体,… }。当你需要访问第一用户时,你只需这样写代码:allUE{1},当你需要访问第一个用户的第一个属性时,你只需要这样写代码:allUE{1}.ID
给一个简单的例子:
numUE=5; %5个用户
allUE=cell(1, numUE); %定义cell数组,allUE
%下边数据我随便设的
for i=1:1:numUE
%这一部分代码已经是在创建UE结构体了
UE.ID = 1;
UE.level = 2;
UE.x= 3;
UE.y= 4;
UE.belongSBS_ID= 5;
UE.minK= 6;
UE.maxK= 7;
UE.stillNeedRBnum= 8;
UE.RBQTable=cell(0); %结构体里边也可以放cell
UE.D= 9;
UE.C= 10;
allUE{i}=UE; %把创建好的UE结构体作为cell数组allUE的元素
end
>> allUE
allUE =
Columns 1 through 4
[1x1 struct] [1x1 struct] [1x1 struct] [1x1 struct]
Column 5
[1x1 struct]
>> allUE{1}
ans =
ID: 1
level: 2
x: 3
y: 4
belongSBS_ID: 5
minK: 6
maxK: 7
stillNeedRBnum: 8
RBQTable: {}
D: 9
C: 10
>> allUE{1}.ID
ans =
1