Assigning different data types to struct arrays using comma separated list assignment. Are there better options?
You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Show older comments
Hi,
To prevent for loops for assigning values in struct arrays I often use comma separated list assignement, like this:
valueVector; % some kind of 1D matrix, which contains, what I want to assing
logIdx; % logical array to assign values
% convert it to a cell array
cnvCell = num2cell(valueVector);
% assign it to the struct array
[structArr(logIdx).mySpecialField] = cnvCell{:};
I like the performance of the code, however, I find it more difficult to read than for-loops. Is there a more elegant way to do a comma separated list assignement?
1 Comment
(I find the conversion to cell arrays as an intermediate step a bit annoying)
Accepted Answer
I like the performance of the code, however, I find it more difficult to read than for-loops
Why not just use for-loops then, if they look better to you? num2cell is no faster.
8 Comments
After researching a bit further I realized, that what I was looking for is the deal() function. This allows to skip the conversion to a cell array to create the comma separated list and is in my applications about 10 times faster than the for-loops.
valueVector; % some kind of 1D matrix, which contains, what I want to assing
logIdx; % logical array to assign values
% assign it to the struct array
[structArr(logIdx).mySpecialField] = deal(valueVector);
"After researching a bit further I realized, that what I was looking for is the deal() function"
This gives a different result to what you showed in your question. In particular, when the input to DEAL is a single array then the complete array is repeatedly allocated to all outputs on the LHS. This is explained in the DEAL documentation: "[B1,...,Bn] = deal(A) copies the single input argument A and returns it as the output arguments B1,...,Bn. It is the same as B1 = A, …, Bn = A."
Whereas your original code uses NUM2CELL to split the provided vector into its constituent individual elements and assigns each of them to the corresponding output on the LHS. So, quite different.
Lets compare them right now:
V = [11,22,33];
[A(1:3).x] = deal(V) % repeatedly assigns the ENTIRE RHS to each output of the LHS
A = 1×3 struct array with fields:
x
A.x
ans = 1×3
11 22 33
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
ans = 1×3
11 22 33
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
ans = 1×3
11 22 33
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
C = num2cell(V);
[B(1:3).x] = C{:} % assigns each ELEMENT of the RHS to the corresponding LHS output
B = 1×3 struct array with fields:
x
B.x
ans = 11
ans = 22
ans = 33
It is clear that these are not the same results.
@Stephen23 is correct, but you can certain write your own mfunction that will deal out elements of a numeric vector:
valueVector = [11,22,33];
logIdx=[1,2,4];
[structArr(1:5).x]=deal(1000);
[structArr(logIdx).x] = dealvec(valueVector);
structArr.x
ans = 11
ans = 22
ans = 1000
ans = 33
ans = 1000
function [varargout]=dealvec(myVector)
varargout=num2cell(myVector);
end
Thank you very much for for pointing this out. That saved me from a big head ache! Indeed I confused the example
x{1} = [];
x{2} = [];
[x{:}] = deal([10 20],[14 12]);
x{:}
ans = 1×2
10 20
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
ans = 1×2
14 12
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
given on that page:
as my solution to the problem, not realizing, that here we have a comma-separated list as an argument to the deal() function, while in my (erroneous) example it was a single variable.
I overlooked this difference and thought, that the behaviour of this example would simply translate to be my solution. I also veryfied this using following code snippet:
% define some data
someLabels = [ ...
"Bla"; ...
"Ble"; ...
"Bli"; ...
"Blo"; ...
"Blu" ...
];
someNumbers = [ ...
1; ...
2; ...
3; ...
4; ...
5 ...
];
% initialize the struct array
structDummy_1(10).someLabels = [];
% initialize the cell array
cellDummy_1 = cell.empty(10,0);
cellDummy_2 = cell.empty(10,0);
% do the assignements to the struct using the conversion via a cell array
cnvCell = num2cell(someLabels);
[structDummy_1(3:7).someLabels] = cnvCell{:};
cnvCell = num2cell(someNumbers);
[structDummy_1(3:7).someNumbers] = cnvCell{:}
structDummy_1 = 1×10 struct array with fields:
someLabels
someNumbers
% do the assignements using deal
[structDummy_2(3:7).someLabels] = deal(someLabels);
[structDummy_2(3:7).someNumbers] = deal(someNumbers)
structDummy_2 = 1×7 struct array with fields:
someLabels
someNumbers
% compare the assignement to the cell array
[cellDummy_1{3:7}] = deal(cnvCell{:})
cellDummy_1 = 1×7 cell array
{0×0 double} {0×0 double} {[1]} {[2]} {[3]} {[4]} {[5]}
[cellDummy_2{3:7}] = deal(someLabels)
cellDummy_2 = 1×7 cell array
{0×0 double} {0×0 double} {5×1 string} {5×1 string} {5×1 string} {5×1 string} {5×1 string}
The link to your TUTORIAL:
was very helpful.
Coming from a C/C++, Pascal background I had a hard time to figure out the philosophy of MATLAB to make use of arrayfun(), cellfun(), ... and so on, to bypass the use of for-loops. While I could already convert all my slow for-loop code using these approaches, I still got stuck with struct arrays like the one example given above.
Becasue the other functions like arrayfun(), cellfun(), ... make well structured, highly-performant and easy-to-read code, I wondered, why there is no simple "MATLAB-style" solution to my above problem. Is there something similar to deal(), which does the same job? This was the purpose behind my original question.
I assume, that structures, like the one above are also a very common thing in MATLAB, created e.g., by regionprops(). However, the tutorial and the "Further Topics" usually do not address the specific case of assinging different values to fields of a struct array. At least I didn't see it in any of these examples.
Is there something similar to deal(), which does the same job? This was the purpose behind my original question.
You can make your own. See my last comment.
Becasue the other functions like arrayfun(), cellfun(), ... make well structured, highly-performant and easy-to-read code
To be clear, arrayfun, cellfun, etc... are not higher performing than a regular for-loop. They are provided by Matlab only as a way to shorten syntax. There is no way to improve upon for-loop speed when working with structs and cells.
"Is there something similar to deal(), which does the same job? This was the purpose behind my original question"
If there was a native MATLAB function for this then I would have mentioned it in my tutorial.
To split up an array into its constituent elements you can use indexing, NUM2CELL, ARRAYFUN, etc.
"...I had a hard time to figure out the philosophy of MATLAB to make use of arrayfun(), cellfun(), ... and so on, to bypass the use of for-loops. While I could already convert all my slow for-loop code using these approaches"
A well-written FOR-loop will (in general) be faster than ARRAYFUN or CELLFUN.
The philosophy of MATLAB is to keep data together and store it in the simplest array type as is reasonable.
"why there is no simple "MATLAB-style" solution to my above problem"
Due to MATLAB's copy-on-write memory management there is conceptually no significant performance disadvantage in the approach you originally used with NUM2CELL: the elements are split and stored in memory, the cell array is transient, and the code is perfectly understandable to a competent MATLAB user.
In my actual application code the switch from loops to this kind of assignment was much more performant (factor 10 or more). However, based on both of your comments I realize, that the reason for the increase in performance might be that I had to vectorize as described in to make this possible:
I consider this question fully answered. I learned a lot. Thank you for your help!
Rik
on 29 Oct 2025
Just a further bit of context: vectorized code in Matlab is generally faster because it forced you to write good code. There can also be an inherent advantage for functions that operate on an entire array at once. If such functions don't exist, a loop will be fast. It used to be true that for-loops resulted in less performant code, but that hasn't really been true since 2 decades (2007b had a big jump IIRC, don't quote me on that, that was well before I even started using Matlab).
The order of performance is usually:
- Vectorized functions (e.g. using mean on an array instead of looping over the elements to compute a sum and dividing by the element count)
- cellfun with the legacy input (although be careful with 'isempty' and 'prodofsize')
- for/while loops
- cellfun/arrayfun/structfun/etc (these are just hiding an internal loop)
More Answers (0)
Categories
Find more on Data Type Identification in Help Center and File Exchange
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)