Size of a structure
Show older comments
After I looked at the Example1 below, I thought the size of a structure was the same as the size of the largest field. However, this concept was conflicted when I looked at the Example2. Can someone please help me to understand how the size of a structure is defined?
Exameple1:
field1 = 'f1'; value1 = zeros(1,10);
field2 = 'f2'; value2 = {'a', 'b'};
field3 = 'f3'; value3 = {pi, pi.^2};
field4 = 'f4'; value4 = {'fourth'};
s = struct(field1,value1,field2,value2,field3,value3,field4,value4)
size: 1×2
Example2:
load fisheriris % Fisher's iris data (1936)
% Create a structure of arrays
fisherIrisStructureOfArrays.species = species;
fisherIrisStructureOfArrays.specimenNumber = [1:150]';
fisherIrisStructureOfArrays.sepalLength = meas(:,1);
fisherIrisStructureOfArrays.sepalWidth = meas(:,2);
fisherIrisStructureOfArrays.petalLength = meas(:,3);
fisherIrisStructureOfArrays.petalWidth = meas(:,4);
Size: 1x1
9 Comments
doc struct
should help with the different ways of constructing a struct. In the second example you create one struct and assign data to it. In the first example you use a specific syntax of the constructor whose behaviour is documented and gives what you have observed.
The syntax taking multiple fields and values states that all nonscalar array inputs must be the same dimension which is the dimension s will have. scalat inputs will be replicated to all cells.
Jan
on 4 Aug 2017
Do you know the "{} Code" button already? You can use it not format selected code such that it is readable. It is your interest to post readable code. Therefore I'm astonished, that a üproper formatting must be suggested several times each day. Are so many users of this forum not interested in others to read their code?!
Christos Saragiotis
on 4 Aug 2017
Lisa, this may be confusing, you're right.
The difference is this:
- when you create a structure using struct (as in Example 1), then it is a structure array, in which the cells must all have the same size (or be scalar cells)whereas fisherIrisStructureOfArrays is a structure of arrays. In this case the size of the structure is the size of its cell arrays (they should all be the same size or scalar cells) or 1-by-1, if none of the values is a cell.
- when you create a structure as in Example 2, then this is a structure (not a structure array) and the fields may be cells of different sizes.
It is unfortunate and confusing that if you use class(s) or class(fisherIrisStructureOfArrays), you get both times struct.
Adam
on 4 Aug 2017
Surely you would expect 'struct' to be the result of asking the class of a struct or struct array?!
@Christos Saragiotis: MATLAB does not distinguish between a "struct" and an array of structures. A "struct" is just a 1x1x1... structure array, in exactly the same way that the value 2 is a 1x1x1... numeric array.
"It is unfortunate and confusing that if you use class(s) or class(fisherIrisStructureOfArrays), you get both times struct."
I don't see why this is confusing at all. It is totally consistent with all of MATLAB arrays: numeric, char, cell, struct, etc. I would not expect
class(2)
to give a different class than
class([1,2;3,4])
so why do you expect a non-scalar structure to have a different class than a scalar structure? Personal question: do you have a programming background?
@Stephen and Christos: It is the nature of Matlab, that scalars are arrays of the size [1x1]. class() does and should reply the class of the object only. If it is a scalar or an array is the job for size() command.
But as usual: As soon as this is clear (but not earlier), it is not confusing anymore, but trivial.
Christos Saragiotis
on 4 Aug 2017
@Adam, Stephen, Jan: The reason why I said it is "unfortunate and confusing" is that the struct of Example 2 allows fields to be cells of different sizes whereas that of Example 1 does not allow a field to be a cell other than one specific size or a scalar cell.
The way I see it, this is an inconsistency between the two struct instances.
Additionally, look at the following example:
field1='f1'; field2='f2'; value1=1:10; value2={'one','two','three'};
s1 = struct(field1,value1,field2,value2);
s2.f1=value1; s2.f2=value2;
size(s1), size(s2)
yields
ans =
1 3
ans =
1 1
If this is not confusing, in any case it is not intuitive at all (unlike most of MATLAB). Of course, if you know what's happening it's not confusing any more.
Adam
on 4 Aug 2017
s1 = struct(field1,value1,field2,value2);
is a convenience function overload though really. It allows you to throw in loads of data to a non-scalar struct all at once rather than build it up in a more verbose manner.
Similarly to the way functions like imagesc take it upon themselves to flip the y axis and make other changes to axes properties rather than just do the raw action of putting your image data on an axes, this is a method that rolls up a potentially large amount of lines of code into one quick way of creating a struct.
These kind of function overloads often require some deeper understanding, in the same way that functions involving meshgrids and their ilk still confuse me.
When working with your own structs rather than arbitrary examples though it should be less confusing because you know what to expect of your structure so its size should not be a surprise and you would just create it in whichever way is best for you. That its class should always be 'struct' though cannot be argued. The size of the struct array it creates certainly may come as a surprise to people new to it (I very rarely use structs myself so I am not familiar with their creation syntax either other than the simple creation as in example 2).
Jan
on 5 Aug 2017
@Christos: I see. You could expect struct(a, {1,2}) to reply a scalar struct. Instead of relying on intuition, I tend to trust the documentation. There I find, that I need a nested cell to create a scalar struct with a cell as value, because cells create a struct array.
I've written a function S = ScalarStruct as C-Mex, but found the benefits too marginal for a daily use or for publishing it in the FEX.
Answers (2)
EB
on 3 Jun 2019
4 votes
transform your structure to table:
size( struct2table(DATA), 2)
If you create a struct by the struct command, the size of the array is determined by the data, if they are provided as a cell array:
S = struct('A', {1, 2}, 'B', 0);
% Now S is a [1 x 2] struct array, because the data for A are given
% as {1 x 2} cell. This is equivalent to:
S(1).A = 1
S(1).B = 0
S(2).A = 2
S(2).B = 0
If you want S to be a scalar and contain the cell {1,2} as field A, use:
S = struct('A', {{1, 2}}, 'B', 0);
% Now S is a scalar struct, because the data for A are provided
% as {1 x 1} cell, which contains the cell {1,2}. This equivalent to:
S(1).A = {1,2}
S(1).B = 0
In the 2nd example, you define the fields of the scalar struct directly. The difference you see comes from the way the struct() command works. Note that this is explained clearly in the documentation:
doc struct
7 Comments
Lisa Lee
on 4 Aug 2017
Jan
on 5 Aug 2017
Note: Even a scalar struct is a struct array of the size [1 x 1]. There is no difference in Matlab.
Robert Scott
on 10 Dec 2023
why has this still not been asnwered
Image Analyst
on 10 Dec 2023
@Robert Scott you can use the size or whos function on the structure or individual fields of the structure.
Walter Roberson
on 10 Dec 2023
If we need to be more explicit:
A scalar struct is a collection of ordered named fields. Inside a scalar struct, each field can contain any collection of data that could be assigned to a regular non-struct variable, of any size and any data type. size() of a scalar struct is defined as 1 x 1
A nonscalar struct is an array (possibly multidimensional), each member of which is a scalar struct. When you have a nonscalar struct, the field names and field order must be the same for each scalar struct within the array, but what the fields hold can be completely different. It is, for example, completely valid to have
s(1,1).name = 'Robert';
s(1,2).name = [];
s(2,1).name = NaN;
s(2,2).name = @(x)x.^2 - 1;
size() of a nonscalar struct is the array dimensions; for example the above would be size 2 x 2.
size() of a struct does not depend in any way on how many fields are in the struct array, and does not depend in any way on the data type or contents of what is in the field.
Robert Scott
on 10 Dec 2023
thanks
There is also a different measure of "size" available.
If you use whos then you can see a field named Bytes that indicates the amount of memory required to store the contents of a variable.
That size excludes the amount of memory needed to describe the variable itself -- does not include the memory needed to store the name of the variable or the size of the variable or the class() of the variable or information such as whether the variable is complex-valued or is global.
For example
A = zeros(3,5,'uint8');
B = zeros(3,5,'double');
C = 'hello';
D = "hello";
whos A B C D
A is 3 by 5 uint8 and each uint8 takes 1 byte, so A is 3 * 5 * 1 = 15 bytes
B is 3 by 5 double and each double takes 8 bytes, so B is 3 * 5 * 8 = 120 bytes
C is 1 x 5 char and each char takes 2 bytes, so C is 1 x 5 x 2 = 10 bytes
D is considered a 1 x 1 string() array. The storage for string() arrays is... odd
- empty string array has 96 bytes overhead
- each additional array entry takes 52 bytes
- those 52 bytes hold up to 10 characters (each 2 bytes per char)
- then the size of the entry goes up by 10 bytes, which holds up to 5 char (2 bytes per char)
- after that, the size of entries goes up in 16 byte increments, which holds up to 8 char (2 bytes per char)
I could more easily understand if the size consistently went up in 16 byte increments, each holding up to 8 chars, but the 10-chars then 5-chars initial bit has me scratching my head.
Anyhow, the point is that the Bytes field of whos() gives a measure of memory size (but not of array size in the sense that size() would return.)
Categories
Find more on Data Type Conversion in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!