Search code examples
matlabtextstructcell-array

Making a struct from a string containing matrices and its names


I actually have a text file containing uint8 data like this:

[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

What I ultimately want is a struct, say A, with fields containing this data as:

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]

So what the above example shows is to find the multiple instances of the matrix and stack them into one. If there is a space in the name, remove the space or replace that with underscore.

Until now, I have:

A = importdata('file.txt');

which creates a cell array (20,000 x 1 for my original data) containing the data. I know the names of the matrices already that the text file will have. So I tried to differentiate the matrices like the following which gives me the cell containing the matrices and its name:

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

How do I proceed? Or What would be a simpler solution to this problem with more speed?


Solution

  • I would use textscan instead of importdata in this case, since you're dealing with mixed data types:

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

    Which gives you the following results in values and fields:

    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'
    

    Now you can replace spaces in fields with underscores using 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, ~, index] = unique(strrep(fields, ' ', '_'));
    counts = accumarray(index, 1);
    [~, sortIndex] = sort(index);
    values = mat2cell(values(sortIndex, :), counts);
    

    Now you can easily put it all together into a structure using 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]