本节归纳 MATLAB 中四类常用数据容器:普通数组、元胞数组、结构体与表格。选型取决于元素是否同类型、是否需要列名,以及数据是否表示带多个属性的对象。同一批信息往往可以放进多种容器,但后续是做矩阵运算、按字段取属性,还是按报表列筛选,会立刻显出差别。
data = { '苹果', 3.5; '香蕉', 2.8; '橙子', 4.2 };
data{2, 1}结果是 '香蕉'。名称和价格可以放进同一个元胞数组,因为各格类型不必相同。若下一步要对价格求平均、画柱状图,把价格单独放进普通数值向量更合适;元胞数组适合先把不同类型放在一起,不适合作为大规模数值运算的主结构。
四个容器对照
| 容器 | 适合存什么 | 索引方式 |
|---|---|---|
| 普通数组 | 同类型数值,要做数学运算 | A(i,j) |
| 元胞数组 cell | 混合数据、无列名 | C{i,j}(花括号取内容) |
| 结构体 struct | 对象式数据,属性有名字 | s.field 或 s(i).field |
| 表格 table | 像电子表格,列有名字 | T.Column |
普通数组要求元素类型一致,才能直接写 A + 1、mean(A)。元胞数组用花括号取出格子里的内容,圆括号只取出格子本身(仍是 1×1 cell),二者不可混用,详见元胞数组。结构体按字段名组织一个对象的多项属性,结构体数组则表示多个同类对象,见结构体。table 带列名,接近 CSV 表头,见表格;GNU Octave 与本站在线编译器通常没有 table,练习时用结构体或元胞数组代替即可。
怎么选
可按下面三条依次判断,而不必同时记住全部接口:
- 元素能否用同一种数值类型表示,并且接下来要做加减乘除或统计?若能,用普通数组。
- 各列是否既有名字、又像一张报表(姓名、年龄、成绩各占一列)?在 MATLAB 中可用
table;若只是临时把不同类型塞进格子,用元胞数组。 - 关心的是一组对象,每个对象有若干属性(例如每个学生有姓名、年龄、成绩)?用结构体或结构体数组,按
s(i).name访问。
混合使用的例子
一个简单的学生记录里,三种容器可以一起用,各自负责一层结构:
% 用 struct 组织每个学生
s1 = struct('name', 'Riya', 'scores', [88 92 85]);
s2 = struct('name', 'Tiya', 'scores', [91 80 94]);
% 用 cell 装不同长度的历史成绩(两学期长度不同,不能放进同一数值矩阵)
s1.history = {[85 90], [88 92 85]};
% MATLAB 中可用 table 汇总全班;Octave 可改用结构体数组
T = table({'Riya';'Tiya'}, {[88 92 85]; [91 80 94]}, ...
'VariableNames', {'Name', 'Scores'})结构体描述单个对象,元胞数组容纳长度不一的历史记录,表格(或结构体数组)汇总全班列表。需要计算全班某次考试平均分时,应先把分数取出为普通数组,再调用 mean,而不是对混合容器直接做矩阵运算。
性能提醒
元胞数组因元素类型可异,逐格访问通常慢于同型数值数组。大规模数值计算应优先使用普通数组,并避免在内层循环中频繁用花括号取元胞。结构体数组在字段很多、对象很多时也会比单纯的数值矩阵慢,数值主流程仍应保持矩阵形态。
本节说明了四类容器的索引方式与选型思路,并给出混合使用的示例。下一节介绍数值与精度:默认 double、整数范围、浮点比较与类型转换。