Struct to cell (or matrix) in Matlab

16,297

Solution 1

First make some example data:

n = 10;

ID         = num2cell(randperm(n)');
Coordinate = mat2cell(randn(n, 3), ones(n,1));
Misc       = num2cell(randn(n,1));
Conn       = arrayfun(@randperm, randperm(n), 'UniformOutput', 0)';

Point = struct('ID', ID, 'Coordinate', Coordinate, 'Misc', Misc, 'Conn', Conn);

Now inspect it:

>> Point

Point = 

10x1 struct array with fields:
    ID
    Coordinate
    Misc
    Conn

>> Point(1)

ans = 

            ID: 7
    Coordinate: [-0.0571 -1.1645 2.4124]
          Misc: 0.0524
          Conn: [3 2 1]

Now use arrayfun() to sweep through the elements of structure array Point. We define a generic function x to operate on each element of Point, formatting the row like you described:

Point_cell = arrayfun(@(x) [num2cell([x.ID x.Coordinate x.Misc]) num2str(x.Conn)], Point, 'UniformOutput', 0);
Point_cell = vertcat(Point_cell{:})

Now inspect the output:

ans = 

    [ 7]    [-0.0571]    [-1.1645]    [ 2.4124]    [ 0.0524]    '3  2  1'            
    [ 5]    [ 0.2918]    [ 0.4948]    [ 0.7402]    [-1.9539]    '1  2'               
    [ 3]    [-0.6146]    [-1.2158]    [ 0.3097]    [ 0.5654]    '3  4  1  2'         
    [10]    [-0.0136]    [ 1.5908]    [-0.5420]    [ 0.0778]              [1x25 char]
    [ 2]    [ 0.4121]    [ 0.5265]    [ 0.1223]    [ 0.0807]              [1x22 char]
    [ 1]    [-0.9371]    [ 0.2648]    [ 0.9623]    [ 0.7947]    '1  2  5  4  3'      
    [ 4]    [ 0.8352]    [-0.3936]    [-0.2540]    [ 1.0437]    '6  2  3  7  4  1  5'
    [ 8]    [ 1.0945]    [-2.1763]    [ 1.8918]    [ 0.8022]    '1'                  
    [ 6]    [ 0.3212]    [-1.1957]    [-1.2203]    [-0.4688]              [1x37 char]
    [ 9]    [ 0.0151]    [ 0.3653]    [-0.3762]    [-0.0466]    '3  5  4  2  6  1'   

Couldn't tell from your question, but if you want all the numeric fields as an array inside a single cell, that is an easy tweak to do. Good luck!

Solution 2

Here is a slightly different solution using STRUCT2CELL:

%# build a sample array of structures
id = num2cell((1:10)',2);    %'
coords = num2cell(rand(10,3),2);
misc = num2cell(rand(10,1),2);
conn = arrayfun(@(n)randi(5,[1 n]), randi([0 6],[10 1]), 'UniformOutput',false);
p = struct('ID',id, 'Coordinate',coords, 'Misc',misc, 'Conn',conn);

%# convert to cell array
h = fieldnames(p)';          %'
X = struct2cell(p)';         %'

%# split 'coords' field into 3 separate columns
h2 = {'xPos' 'yPos' 'zPos'};
X2 = num2cell( cell2mat(X(:,2)) );

%# convert 'conn' field to string
X4 = cellfun(@num2str, X(:,4), 'UniformOutput',false);
X4 = regexprep(X4, '[ ]+', ' ');    %# clean multiple spaces as one

%# build final cell array with headers
C = [h(1) h2 h(3:4) ; X(:,1) X2 X(:,3) X4]

The result:

>> C
C = 
    'ID'    'xPos'       'yPos'        'zPos'       'Misc'        'Conn'       
    [ 1]    [0.78556]    [ 0.46707]    [0.66281]    [ 0.46484]    '3'          
    [ 2]    [0.51338]    [  0.6482]    [0.33083]    [ 0.76396]    '2 1 2 5 1 2'
    [ 3]    [ 0.1776]    [0.025228]    [0.89849]    [  0.8182]    '1 3 1 5'    
    [ 4]    [0.39859]    [ 0.84221]    [0.11816]    [ 0.10022]    '1 1 2'      
    [ 5]    [0.13393]    [ 0.55903]    [0.98842]    [ 0.17812]    '3 1 5 2 2 1'
    [ 6]    [0.03089]    [  0.8541]    [0.53998]    [ 0.35963]    ''           
    [ 7]    [0.93914]    [ 0.34788]    [0.70692]    [0.056705]    '2 1 3 4 4'  
    [ 8]    [0.30131]    [ 0.44603]    [0.99949]    [ 0.52189]    '1 1 4 5 3'  
    [ 9]    [0.29553]    [0.054239]    [0.28785]    [ 0.33585]    '1 5 2'      
    [10]    [0.33294]    [ 0.17711]    [0.41452]    [ 0.17567]    '2'     

where for example the second structure was:

>> p(2)
ans = 
            ID: 2
    Coordinate: [0.51338 0.6482 0.33083]
          Misc: 0.76396
          Conn: [2 1 2 5 1 2]
Share:
16,297
user1007692
Author by

user1007692

Updated on July 30, 2022

Comments

  • user1007692
    user1007692 almost 2 years

    I have a structure with fields ID,Coor,Misc,Conn. ID and Misc are doubles, however, Coor is a 1x3 vector and Conn is a 1xn vector (where n can theoretically be from 0 to inf).

    Point(x).ID = [x]
    Point(x).Coordinate = [xPos yPos zPos]
    Point(x).Misc = [randomDouble]
    Point(x).Conn = [someVectorOfNumbers]
    

    I would like to have this mapped on a cell array, without using a FOR loop.

    An example of the output:

    'ID    xPos    yPos    zPos    Misc    Conn'
     1      0        0       0       0    '0 1 2'
     2      1        1       1       1      ''     
     ...
     x      x        x       x       x      '2'
    

    Notice that Point.Conn, its vector of numbers gets converted into a string.

    The issues that I am having is breaking up Point.Coordinate into its three elements, and converting Point.Conn into a string.

    I feel like this can be done using struct2Cell and then changing the nesting level. I'm just not exactly sure how to do that.