1、前言
大概混合编程是每个编程者终将会面临的一个难题,其首先面临且必须解决的问题便是数据类型转换。每一个转换错误都将扼杀还是胎儿时期的混编代码。这里,仅将介绍MATLAB的结构体数据类型 ,转向Python的字典类型。
2. 代码分析
MATLAB的结构体是由一个个field-value对组成,这像极了Python的字典。但是!当你将其保存成.mat文件,然后由Python加载,你会发现,字典的键值对存储的是变量名-所有value(指上面的value)。这样的效果是不符合需要的。而且,这样直接加载,会造成数据错误。下面是一种错误示范:
我的结构体变量名是VObj,包含了3个5个三维数组、1个4维数组,和若干普通数值变量。先看最后一行,dict_keys显示的是直接加载后的keys。可以看见,该变量名被当成了python字典的键值了。dict_keys上面输出的是它的数据(图中仅显示部分),dtype后面可以看见,这数据已经混乱了。
我们必须得把结构体的field-value对提取出来,变成一个个变量,然后再存储在同一个.mat文件中,Python加载.mat后赋值给一个变量就直接完成了字典构建。
3. 关键函数
实现field-value对的提取,如果对数很少可以用本方法,在matlab中直接存储,即存储多变量到一个.mat中。所有,本文旨在自动完成field-value的提取,无视对数的多少。
关键函数有三:
- fieldnames(StructObject):返回结构体的field,存储在cell数组中。
以我的结构体VObj为例:
2.whos(’-file’,[pathname filename]):返回文件信息,用它来自动获取变量名,用于指定该变量。
还是以我的VObj为例:
- eval(string):执行string表示的matlab命令,必须是字符结构。这是比较高级的命令函数,具有灵活多变的特点。
在for循环中,可以依次添加结构体各个field-value对为新的变量,然后保存在.mat中。就相当于一个不定命令:
save AA.mat N1 N2 N3 N4 N5 ... Nn
具体代码是:
pros=fieldnames(var.(s.name));
saveVar=[];
for i=1:length(pros)
eval([pros{i} '=var.(s.name).' pros{i} ';']);
saveVar=[saveVar ' ' pros{i}];
end
name=filename(1:end-4);
eval(['save ' name '.Mat2Py.mat' saveVar ';']);
以上就是基本函数。
4. 完整代码
这里使用了uigetfile来创建一个文件选择对话框,可以很便捷的选择指定文件。
顺便说一下,这是MATLAB的结构体.mat文件,转化给Python字典加载的.mat文件。如果你要使用该文件,需要将欲转化的结构体先保存成.mat文件。.mat文件的文件名为name.Mat2Py.mat,如果你可以在最后一行中自行修改。
[filename,pathname,filterindex]=uigetfile();
var=load([pathname filename]);
s=whos('-file',[pathname filename]);
pros=fieldnames(var.(s.name));
saveVar=[];
for i=1:length(pros)
eval([pros{i} '=var.(s.name).' pros{i} ';']);
saveVar=[saveVar ' ' pros{i}];
end
name=filename(1:end-4);
eval(['save ' name '.Mat2Py.mat' saveVar ';']);