从包含矩阵及其名称的字符串创建结构

Making a struct from a string containing matrices and its names

我实际上有一个包含 uint8 数据的文本文件,如下所示:

[0, 18, 121] bl
[0, 19, 12] gt
[24, 19, 22] apa
[0, 18, 1] bl
[24, 19, 22] apa bpa
[1, 2, 3] apa

我最终想要的是一个结构,比如 A,其中包含此数据的字段为:

A.bl= [0, 18, 121;
       0, 18, 1  ];
A.gt = [0, 19, 12];
A.apa = [24,19,22];
A.apa_bpa = [24,19, 22]    or A.apabpa= [24, 19, 22]

所以上面的例子展示的是找到矩阵的多个实例并将它们堆叠为一个。如果名称中有 space,请删除 space 或将其替换为下划线。

到目前为止,我有:

A = importdata('file.txt');

创建一个包含数据的元胞数组(我的原始数据为 20,000 x 1)。我已经知道文本文件将具有的矩阵的名称。所以我试着像下面这样区分矩阵,它给了我包含矩阵及其名称的单元格:

A(~cellfun(@isempty, strfind(A,'bl')))

我该如何进行?或者有什么更简单的解决方案可以更快地解决这个问题?

如果您的文件相当长,格式良好并且您不想在 eval 中使用糟糕的东西,我建议您使用通过 setfield 设置结构字段的旧样式

% I just copied data from top of the post to the document
fid = fopen('testdoc.txt');
store_struct = struct();
while ~feof(fid)
    tmp_line = fgetl(fid);
    delim_idx = find(tmp_line == ']');
    tmp_mat=uint8(str2num(tmp_line(2:delim_idx-1)));
    tmp_field = deblank(tmp_line(delim_idx+2:length(tmp_line)));
    tmp_field(tmp_field == ' ') = '_';
    if isfield(store_struct,tmp_field)
        store_struct = setfield(store_struct,tmp_field,...
            [getfield(store_struct,tmp_field);tmp_mat]);
    else
        store_struct = setfield(store_struct,tmp_field,...
            tmp_mat);
    end
end
fclose(fid);

在这种情况下我会使用 textscan instead of importdata,因为您处理的是混合数据类型:

fid = fopen('file.txt');
data = textscan(fid, '[%d%d%d%s', 'Delimiter', ',]', 'CollectOutput', true);
fclose(fid);
values = data{1};
fields = data{2};

valuesfields 中得到以下结果:

values =
  6×3 int32 matrix

     0    18   121
     0    19    12
    24    19    22
     0    18     1
    24    19    22
     1     2     3

fields =
  6×1 cell array

    'bl'
    'gt'
    'apa'
    'bl'
    'apa bpa'
    'apa'

现在您可以使用 strrep, find the unique strings with unique, get the number of repeats of each string with accumarray, sort the rows of values to match the list of unique field names, and group rows of values using mat2cell:

fields 中的空格替换为下划线
[fields, ~, index] = unique(strrep(fields, ' ', '_'));
counts = accumarray(index, 1);
[~, sortIndex] = sort(index);
values = mat2cell(values(sortIndex, :), counts);

现在您可以使用 cell2struct:

轻松地将它们组合成一个结构
S = cell2struct(values, fields)

S = 
  struct with fields:

        apa: [2×3 int32]
    apa_bpa: [24 19 22]
         bl: [2×3 int32]
         gt: [0 19 12]

您可以按照 gnovice 的建议使用 textscan 来读取数据

fid = fopen('file.txt');
data = textscan(fid, '[%d%d%d%s', 'Delimiter', ',]', 'CollectOutput', true);
fclose(fid);
values = data{1};
fields = data{2};

然后使用一个简单的循环来创建结构,因为您可以使用圆括号通过字符串访问结构的字段

% demo for accessing fields
myStruct.myField 
% is equivalent to
myStruct.('myField')

所以:

% Replace spaces with underscores in 'fields'
fields = strrep(fields, ' ', '_');
% Initialise struct
A = struct;
% Loop over fields, assign values
for ii = 1:numel(fields)
    if isfield(A,fields{ii})
        % Append to array if field already exists
        A.(fields{ii}) = [A.(fields{ii}); values(ii,:)];
    else
        % Create field as array if doesn't yet exist
        A.(fields{ii}) = values(ii,:);
    end
end