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

时间:2017-08-21 15:38:16

标签: matlab text struct cell-array

我实际上有一个包含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]

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

到现在为止,我有:

A = importdata('file.txt');

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

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

我该怎么办?或者以更快的速度解决这个问题的更简单方法是什么?

3 个答案:

答案 0 :(得分:4)

在这种情况下,我会使用textscan而不是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用下划线替换fields中的空格,找到unique的唯一字符串,使用accumarray获取每个字符串的重复次数,{ {3}} values行匹配唯一字段名称列表,并values使用sort对行进行分组:

[fields, ~, index] = unique(strrep(fields, ' ', '_'));
counts = accumarray(index, 1);
[~, sortIndex] = sort(index);
values = mat2cell(values(sortIndex, :), counts);

现在,您可以使用mat2cell轻松将所有内容整合到一个结构中:

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]

答案 1 :(得分:1)

如果您的文件相当长,格式正确,并且您不想在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);

答案 2 :(得分:1)

您可以使用textscan作为gnovice建议读取数据

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