处理多维数组时,经常遇到 1×1×100 或者 3×1×5 这种带多余边长 1 的形状。画图、传给函数、做插值,往往要求是 1×100 或者 3×5,于是就得用 squeeze 压一下。
它只做一件事
把数组里长度为 1 的维度去掉,其他维度保持原顺序不变。
A = rand(1, 1, 100);
B = squeeze(A);
size(B) % 100 1注意 1×1×100 压完是 100×1 的列向量,不是 1×100 的行向量。这一点经常让人踩坑:后面按列取数据时得到的形状和预想相反,转置一次就好了。
它不会把二维变成标量以外的东西
如果输入本来就是二维 1×5,squeeze 会把它变成 5×1;如果输入是 5×5,squeeze 什么也不做,原样返回。规则只看维度长度,不看数值。
size(squeeze(ones(1, 5))) % 5 1
size(squeeze(ones(5, 5))) % 5 5
size(squeeze(ones(1, 1, 1))) % 1 1最后那种情况要注意,全是 1 的多维数组压完会变成标量,有时候会让后续的索引报错。
常见的使用场景
- 循环里累积结果:每次得到 1×1×N 的结果,拼起来之后压成矩阵。
- 图像数据处理:单通道图像读进来是 H×W×1,压掉最后一维才能被某些函数接受。
- 画图报错:plot 不接受三维数组,先 squeeze 再画。
- 函数返回值:自定义函数输出 1×1×K,调用方拿来直接用会更顺手。
和 reshape 的区别
reshape 是按你指定的新尺寸重排元素,数据一个不动,形状完全由你决定,写错顺序就会打乱元素位置。squeeze 只删长度为 1 的维度,安全得多,不会改变元素顺序。所以能用 squeeze 解决的就别用 reshape。
另外,想让结果固定成行向量,可以在 squeeze 之后再接 (:).',避免列向量带来的连锁问题:
v = squeeze(A);
v = v(:).';一个小函数,用对地方能省掉很多尺寸不匹配的报错。