MATLAB 学习笔记——3. 结构体数组和元胞数组
在编程实践中,仅仅只靠浮点数数组还是不够的,我们还需要其他更灵活的数据结构(运行效率也会更慢),最常见的数据结构是结构体数组和元胞数组。
结构体数组
虽然MATLAB官方将其称为结构体数组,但是实际上不管是从使用还是实现的角度,将其称为字典都更合适。在C++的语境中,结构体约等于自定义类型,而对于MATLAB,自定义类型和结构体数组是截然不同的。
结构体数组(struct)是 MATLAB 中一种非常灵活的具名数据类型,可以将不同类型的数据直接组合在一起,每个字段具有名称,可以包含不同类型和大小的数据,结构体数组使得组织和管理复杂数据更加方便。
结构体数组的使用非常灵活,可以使用点符号直接创建
1 | % 此前person未定义 |
需要注意的是,这里的person
变量尚未定义,否则上述语句只有在person
已经是一个结构体数组时才会成立,此时的效果是创建或修改对应的字段。
对未定义变量直接操作的语法糖导致我们可能无意之间写出错误的语句,例如一个错误的变量名就会导致创建了一个新的结构体数组,而非对已有的结构体数组的字段进行操作,这个错误还非常隐蔽。(MATLAB的语法设计真是太合理了)
我们还可以使用struct
函数创建,一次性添加多个字段以及对应的数据
1 | person = struct('name', 'Jane Doe', 'age', 28, 'height', 1.65); |
结构体数组并没有明确完整的创建过程,我们可以在任何时间自由地向结构体数组中添加字段,或对现有字段进行访问和修改。 每一个结构体数组都是完全独立的,对于这个结构体数组可以有(或者必须有)哪些字段没有任何要求
1 | disp(person.name); % 输出:John Doe |
尝试读取不存在的字段会导致错误。
我们可以使用内置函数isfield
来检查结构体数组是否具有某个字段
1 | % 检查字段 |
我们可以使用内置函数rmfield
来移除结构体数组的字段,需要用返回值重新赋值
1 | % 删除字段 |
从上面的介绍可以看出,结构体数组实际上就是一个键为字符串的字典,语法非常灵活,易与后文中的面向对象的语法产生冲突,因此决定尽量避免使用结构体数组,转而使用更安全的面向对象的语法!
元胞数组
元胞数组是一种包含名为cell的索引数据容器的数据类型,其中的每个cell都可以包含任意类型的数据。
元胞数组可以包含文本列表、文本和数字的组合或者不同大小的矩阵等,通常用于打包一组矩阵或多组矩阵。
通过将索引括在圆括号()
中可以引用cell,使用花括号{}
进行索引来直接访问cell的内容,两者区别见下文。
元胞数组的创建方式如下,元胞数组通常使用二维的结构,m行n列,每一个元素是一个矩阵或其他任何对象,元胞数组也支持多维的定义和操作。
1 | C1 = {}; % 空的元胞数组 |
可以定义指定尺寸的,每一个元素均为空矩阵的元胞数组:
C = cell(n)
,返回由空矩阵构成的\(n\times n\)元胞数组。(注意这不是 \(1\times n\) 或 \(n \times 1\))C = cell(s1,...,sn)
返回由空矩阵构成的 \(s_1 \times \dots \times s_n\) 元胞数组。例如,cell(2,3)
返回一个 \(2\times 3\) 元胞数组。C = cell(a)
返回由空矩阵构成的元胞数组,并由行向量a来定义尺寸,例如,cell([2 3])
返回一个 \(2\times 3\) 元胞数组。(使用列向量是非法操作)
元胞数组和普通矩阵一样,可以在赋值的同时直接进行扩充,并且与矩阵不同,元胞数组支持不同的数据组成cell
1 | C = {'2017-08-16',[56 67 78]}; % size 1*2 |
此时()
和{}
索引得到的结果是不同的
1 | >> C(1,1) |
前者仍然是一个 \(1\times 1\) 的元胞数组,后者得到的则是实际的矩阵或字符串。
基于花括号{}
索引获取分量或矩阵之后,就可以直接赋值和修改了,甚至并不需要初始化,直接赋值就可以使用
1 | % x is undefined |
元胞数组是可以嵌套的,嵌套并不等价于元胞数组的二维结构!
1 | D1 = {1,2,3; |
结构体数组和元胞数组转换
使用内置函数filedsname
可以基于结构体数组的所有字段名,创建为一个\(n \times 1\)的元胞数组,例如
1 | >> person = struct('name', 'Jane Doe', 'age', 28, 'height', 1.65); |
与之对应的是,使用内置函数struct2cell
可以基于结构体数组所有字段的值,创建为一个\(n \times 1\)的元胞数组,例如
1 | >> person = struct('name', 'Jane Doe', 'age', 28, 'height', 1.65); |
使用内置函数cell2struct
可以通过存储字段名和值的元胞数组,创建对应的结构体数组
1 | cellArray = {'John Doe', 30, 1.75}; |
需要注明的是,第三个参数是创建结构体数组所使用的维度。