문제

Is there a fast/nice way to convert a structure of structures to an array?

s1 = struct('v', 1);
s2 = struct('v', 2);
s = struct('s1', s1, 's2', s2);

I expect an array of .v:

[1, 2]

Reason: I need to pass a Simulink.Parameter (which is a struct of structs of structs etc) to a C S-function and I was thinking about serializing it by making it an array of doubles (which is contiguous in memory) and then I recast it to my struct definition in C.

도움이 되었습니까?

해결책 2

This resursive function works for any depth level and is more compact:

function arr = f_struct2array(S, arr)
    if (isa(S, 'double'))
        arr = [arr S];
    else
        SNames = fieldnames(S); 
        for i = 1:numel(SNames) 
            arr = f_struct2array(S.(SNames{i}), arr);
        end
    end
end

다른 팁

Method 1:

s1 = struct('v', 10);
s2 = struct('v', 20);
s3 = struct('v', 30);
s4 = struct('v', 40);

s = struct('s1', s1, 's2', s2,'s3', s3, 's4', s4);

n1 = fieldnames(s);
for k1 = 1:numel(fieldnames(s))
    array1(k1) = getfield(getfield(s,char(n1(k1))),'v');
end

Output

array1 =

    10    20    30    40

Method 2: Use cell array for the same result -

cell_array1 = struct2cell(s);
for k1 = 1:numel(fieldnames(s))
    array1(k1) = cell_array1{k1,1}.v;
end

Method 3: Use cell array without loop for the same result -

array1 = cellfun(@(x) x(:,1).v,struct2cell(s))';

Extended Part: This is for a case where we have a struct of struct of struct..(inception style?)

%%// Let us create a struct of struct of struct as "s"
s11 = struct('v', 10);
s12 = struct('v', 20);
s13 = struct('v', 30);
s14 = struct('v', 40);

s1 = struct('s11', s11, 's12', s12,'s13', s13, 's14', s14);

s11 = struct('v', 110);
s12 = struct('v', 120);
s13 = struct('v', 130);
s14 = struct('v', 140);

s2 = struct('s11', s11, 's12', s12,'s13', s13, 's14', s14);

s = struct('s1', s1, 's2', s2);

%%// Processing
cell1 = struct2cell(s);
array1 = cellfun(@(x) x(:,:).v,struct2cell(vertcat(cell1{:})))'

Output

array1 =

    10    20    30    40
   110   120   130   140

Extended Part 2: If you want to go one more level deeper, use this -

%%// Let us create a struct of struct of struct as "s_1"
s11 = struct('v', 10);
s12 = struct('v', 20);
s13 = struct('v', 30);
s14 = struct('v', 40);

s1 = struct('s11', s11, 's12', s12,'s13', s13, 's14', s14);

s11 = struct('v', 110);
s12 = struct('v', 120);
s13 = struct('v', 130);
s14 = struct('v', 140);

s2 = struct('s11', s11, 's12', s12,'s13', s13, 's14', s14);

s_1 = struct('s1', s1, 's2', s2);


%%// Let us create a struct of struct of struct as "s_2"
s11 = struct('v', 0.1);
s12 = struct('v', 0.2);
s13 = struct('v', 0.3);
s14 = struct('v', 0.4);

s1 = struct('s11', s11, 's12', s12,'s13', s13, 's14', s14);

s11 = struct('v', 0.01);
s12 = struct('v', 0.02);
s13 = struct('v', 0.03);
s14 = struct('v', 0.04);

s2 = struct('s11', s11, 's12', s12,'s13', s13, 's14', s14);

s_2 = struct('s1', s1, 's2', s2);

%% Finally you would have s
s = struct('s_1', s_1, 's_2', s_2);

%%// Processing
cell1 = struct2cell(s);
for k2 = 1:2
    val1 = cell1{k2,1};
    t1 = struct2cell(val1);
    for k1=1:2
        array1(k1,:,k2) = cellfun(@(x) x(:,:).v,struct2cell(t1{k1,:}))';
    end
end

Output

array1(:,:,1) =

    10    20    30    40
   110   120   130   140


array1(:,:,2) =

    0.1000    0.2000    0.3000    0.4000
    0.0100    0.0200    0.0300    0.0400

Note: If you intend to go more levels deeper, just define more for loops and increase the dimension for array1.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top