How to create an empty array of structs?
    130 Ansichten (letzte 30 Tage)
  
       Ältere Kommentare anzeigen
    
    Fred Sigworth
      
 am 2 Aug. 2011
  
    
    
    
    
    Bearbeitet: Stephen23
      
      
 am 16 Apr. 2025
            I would like to make a loop that accumulates an array of structures, such as
array=struct([]); % The docs imply that this should work
for i=1:n
st=CreateAStruct(i);
array(i)=st;
end;
But...this doesn't work, I get the error, "Subscripted assignment between dissimilar structures." on the first pass through the loop. Instead the only way I've found to do this is the following.
 for i=1:n
  st=CreateAStruct(i);
  if i==1
    array=st;
  else
    array(i)=st;
  end;
end;
Is there a nicer way to do this?
4 Kommentare
  Stephen23
      
      
 am 19 Okt. 2021
				
      Bearbeitet: Stephen23
      
      
 am 19 Okt. 2021
  
			Several "Answers" on this thread were written without a clear understanding of the actual problem and task.
As a demonstration and simple test case I wrote this function (below). To keep it simple it must be called in monotonic sequence with step 1 or -1, i.e. either 1, 2, ... N-1, N or N, N-1, ... 2, 1.
% do not attempt to preallocate array
for k = 7:-1:1
    array(k) = CreateAStruct(k);
end
display(array)
array = CreateAStruct(1);
for k = 2:7
    array(k) = CreateAStruct(k);
end
display(array)
Simple test function:
function sso = CreateAStruct(itr)
nmf = 5; % number of fields
nmc = 3; % number of characters per fieldname
persistent fnm prv
if isempty(fnm) || abs(itr-prv)~=1
    fnm = cellstr(char(randi([65,90],nmf,nmc)));
end
sso = cell2struct(num2cell(rand(nmf,1)),fnm,1);
prv = itr;
end
Akzeptierte Antwort
  Walter Roberson
      
      
 am 2 Aug. 2011
        You are correct, struct() is a struct with no fields, and that is a distinct structure that is not the same as a structure with any defined fields.
Workaround:
T = arrayfun(@(K) CreateAsStruct(K), 1:n, 'UniformOutput',0);
array = horzcat(T{:});
clear T
Also, if I recall correctly, there is a MATLAB File Exchange contribution to do assignment between dissimilar structures.
4 Kommentare
  tommsch
 am 20 Jul. 2020
				@Fred No need to learn arrayfun and anonymous functions. Those are magnitudes slower than plain for loops.
Weitere Antworten (12)
  Fernando Freitas Alves
      
 am 27 Mai 2020
        
      Bearbeitet: Fernando Freitas Alves
      
 am 27 Mai 2020
  
      Since R2008a, you can do:
array = struct.empty(n,0);
Once you cannot assign dissimilar structs and this struct has no field, this is useless.
A better approach would be:
array(n,1) = struct('field1',[],'field2',[],...);
0 Kommentare
  Philip Borghesani
    
      
 am 13 Jan. 2017
        Actualy the simplest and fastest solution to this problem is to not attempt to create an empty struct. Run the loop backwards to allocate the full structure array on the first loop:
 % do not attempt to preallocate array
 for i=n:-1:1
    array(i)=CreateAStruct(i);  
 end
3 Kommentare
  Jeff Miller
      
 am 25 Jan. 2018
				Unfortunately this doesn't work with parfor, because its range must be increasing consecutive integers. But this seems OK:
array(n)=CreateAStruct(n);
parfor i=1:n-1
    array(i) = CreateAStruct(i)
end
  Walter Roberson
      
      
 am 16 Apr. 2025
				parfor starts iterating from the end of the range, so that variables are properly sized from the beginning.
  Dien Nguyen
 am 11 Apr. 2018
        Simple solution, use repmat to "repeat" "n" struct(s) as shown:
array = repmat(struct(field1, [], field2, [], ..., fieldN, []), n);
1 Kommentar
  Walter Roberson
      
      
 am 11 Apr. 2018
				This does not satisfy the original requirement that the struct entry be the result of executing CreateAStruct with argument equal to the index.
  Sean de Wolski
      
      
 am 2 Aug. 2011
        st = 1:10;
for ii = 1:10
  array(ii).st = st(ii);
end
You need to set the value to a field of the struct since that's how structs are indexed. You could also look into using cell arrays:
doc cell
3 Kommentare
  Nathaniel Jones
 am 12 Jun. 2017
				Sean, using a cell array of structs results in the following error when attempting to assign structs as elements of the cell array:
Conversion to cell from struct is not possible.
At this point, you might want to use
cell2struct()
to convert from a cell array to an array of structs. However, Romesh's answer is a better option.
  Samuel
 am 3 Dez. 2013
        It's easy. test(10,10) = struct; This creates an 10*10 empty structs.
1 Kommentar
  Walter Roberson
      
      
 am 11 Apr. 2018
				This does not satisfy the original requirement that the struct entry be the result of executing CreateAStruct with argument equal to the index.
  DAEHO KIM
 am 5 Apr. 2021
        when I pre-allocate the struct array, I do as follows
array(1: n)= struct;
for iter= 1: n
    array(iter).a= "anything"
    array(iter).n= "nothing"
end
3 Kommentare
  DAEHO KIM
 am 6 Apr. 2021
				
      Bearbeitet: DAEHO KIM
 am 6 Apr. 2021
  
			Thank you. 
There is an application version.
% pre-allocate array structure.
array(1: n)= struct;
for iter1= 1: n
    array(iter1).a= "anything";
    array(iter1).n= "nothing";
    % pre-allocate array2 structure in the array structure.
    array(iter1).array2(1: m)= struct;
    for iter2= 1: m
        array(iter1).array2(iter2).e= "everything";
    end
end
  David Young
      
 am 21 Jan. 2014
        For a description of the different kinds of empty structs, and a function that allows you to create each kind easily, see my File Exchange submission emptyStruct
1 Kommentar
  Stephen23
      
      
 am 25 Jan. 2023
				This requires that the structure fields are known in advance, which is not what the question requested.
  Francesco Onorati
 am 13 Jan. 2017
        
      Bearbeitet: Francesco Onorati
 am 13 Jan. 2017
  
      array(n)=struct(field1, [], field2, [], ..., fieldN, []); % <-- as CreateAStruct struct
for i:n
    array(i)=CreateAStruct(var1(i), var2(i));
end
1 Kommentar
  Stephen23
      
      
 am 19 Okt. 2021
				This requires that the structure fields are known in advance, which is not what the question requested.
  Bruno Luong
      
      
 am 20 Jul. 2020
        
      Bearbeitet: Bruno Luong
      
      
 am 20 Jul. 2020
  
      Been there, done that. The most generic way I deal with such situation is like that using a function CATSTRUCT I have created (attached here).
Usage is typically like this:
cellresult = cell(1,n)
for i=1:n
    % do something first
    % ...
    % call iteration subtask that returns a structure or structure array
    cellresult{i} = myfun(i, var1, var2, etc);
    % do something else
    % ...
end
dim = 2; % whatever elongation of structresult you want to get
structresult = catstruct(dim, cellresult); % function mfiles attached
The function CATSTRUCTS can deal with a list of structures that are all dissimilar, so very generic possible usage. The function MYFUN is allowed to return disimilar structures from iteration to iteration. This of course have some speed penalty when structure are concatenated at the last statement compared to stock functions such as horzcat, vertcat, cat(dim, c{: )).
The solution I propose does not require to know in advance the fieldnames of the structure.
PS: TMW can inspire of my small utilities and include in their next MATLAB releases if they wish. 
1 Kommentar
  Bruno Luong
      
      
 am 28 Feb. 2022
				Anotherway is to use the attached file AllocateStruct with the structure element has identical fileds
for i=1:n
    s = myfun(i, var1, var2, etc);
    if i == 1 % ~exist('sarray', 'var')
        sarray = AllocateStruct(s, [1 n]);
    end
    sarray(i) = s;
end
  Owen Claxton
 am 19 Okt. 2021
        Minimum working example:
struct_array_col = [struct()];
struct_array_row = [struct()];
n_structs = 10;
for i = 1 : n_structs
    struct_array_col(i,1).name = num2str(round(rand(1) .* 100, 3));
    struct_array_row(i).name = num2str(round(rand(1) .* 100, 3));
end
disp(size(struct_array_col))
disp(size(struct_array_row))
2 Kommentare
  Owen Claxton
 am 11 Nov. 2021
				
      Bearbeitet: Owen Claxton
 am 11 Nov. 2021
  
			Thanks Stephen, after encounting the problem actually described in the question I realised my error. Leaving my answer up just in case it helps someone. Personally, I went with the preallocation approach as I knew the struct fields (thus I could make an array with similar objects):
section_pieces = struct('type', '', 'slength', 0, 'radius', 0, 'sectionID', 0);
for i = 1 : num_sections
    section_pieces(i) = sectionSpec(section_types{i}, section_lengths(i), section_radii(i), i);
    % sectionSpec creates a struct with type (char array), slength (int),
    % radius (int), sectionID (int) fields using some input arrays
end
  Lihan Xie
 am 25 Feb. 2022
        
      Bearbeitet: Lihan Xie
 am 25 Feb. 2022
  
      The most simple way to get the struct array :
array=[];
for i=1:n
    st=CreateAStruct(i);
    array=[array st];
end
1 Kommentar
  Walter Roberson
      
      
 am 27 Feb. 2022
				That is inefficient, as it has to keep expanding the struct array. Philip's code at https://www.mathworks.com/matlabcentral/answers/12912-how-to-create-an-empty-array-of-structs#answer_250471 is more efficient.
  Cameron
 am 15 Apr. 2025
        Empty_Struct_Array = repmat(struct,0,0)
The simplest solution I can think of... unsure about optimizing computation efficiency, but it's a single line of code.
2 Kommentare
  Walter Roberson
      
      
 am 16 Apr. 2025
				This does not satisfy the original requirement that the struct entry be the result of executing CreateAStruct with argument equal to the index.
  Stephen23
      
      
 am 16 Apr. 2025
				
      Bearbeitet: Stephen23
      
      
 am 16 Apr. 2025
  
			No, this fails the requirement to be able to allocate a new scalar structure on each loop iteration without knowing their fieldnames in advance. Your untested code fails with exactly the same error as the OP reported fourteen years ago. Lets test it now:
Empty_Struct_Array = repmat(struct,0,0); % Your answer
for k = 1:7
    Empty_Struct_Array(k) = CreateAStruct(k)
end
Siehe auch
Kategorien
				Mehr zu Data Type Identification finden Sie in Help Center und File Exchange
			
	Produkte
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!




















