allocate array to structure, error "Scalar structure required for this assignment."

3 views (last 30 days)
im trying to allocate numeric array to all cells in certain field of structure.
mpData(i).data.speed = interp1(x,v,xq);
and get error "Scalar structure required for this assignment."
both interp1(x,v,xq) and mpData(i).data.speed are 168x1 double but still, I get this error.
[mpData(i).data.speed] = deal(interp1(x,v,xq));
wont work since it just allocated all 168 arrays to each cell of mpData(i).data.speed struct. Also num2cell wont work
  2 Comments
Stephen23
Stephen23 on 11 Nov 2024
Edited: Stephen23 on 11 Nov 2024
@Sven Larsen: please save your structure in a MAT file and upload it here by clicking the paperclip button.
Descriptions of non-scalar structures are usually incorrect, which makes answering the question hard/impossible. With your actual structure answering is easier.
Sven Larsen
Sven Larsen on 11 Nov 2024
Edited: Sven Larsen on 11 Nov 2024
Hi. my struct is humongous. but here is snapshot:
as you see, there is already data in mpData(1).speed. I just need to reallocated there new data

Sign in to comment.

Answers (1)

Stephen23
Stephen23 on 11 Nov 2024
Edited: Stephen23 on 11 Nov 2024
The error is easy to replicate given a scalar structure** on the LHS, which contains a non-scalar structure DATA (in your case with 168 elements). The RHS is basically irrelevant, as long as it is one array. Assuming that i is scalar:
mpData(1).data = struct('speed',cell(1,168));
mpData(2).data = struct('speed',{}) % optional, serves no purpose here.
mpData = 1x2 struct array with fields:
data
try % what you are doing -> error
mpData(1).data.speed = 1:168
catch ME
ME.message
end
ans = 'Scalar structure required for this assignment.'
The error occurs because you are trying to assign one array on the RHS to 168 structure elements on the LHS. That will not work (except with DEAL, which is unlikely to be what you want to achieve).
Using NUM2CELL works without error, by creating 168 separate (scalar) arrays that can be allocated to 168 elements of the DATA structure:
C = num2cell(1:168);
[mpData(1).data.speed] = C{:}
mpData = 1x2 struct array with fields:
data
Checking the 2nd element of the DATA structure:
mpData(1).data(2).speed
ans = 2
Learn more about comma-separated lists:
For the Future
Based on your previous question:
here is a little guide to thinking about this operation:
  • just like solving any other mathematical/engineering problem, reduce the problem to something simpler by getting rid of everything superfluous and causes clutter,
  • this means forget about MPDATA: as long as all parent structures are scalar then they are irrelevant, you only really need consider the first (nested) non-scalar structure. And in your case that is DATA, which (apparently) has 168 elements. Luckily you do not have any structures nested within that (which would require a loop or other tricks),
  • Your goal is to allocate 168 separate arrays to 168 separate locations in a structure, i.e. your operation is requires two comma-separated lists, one on the LHS and one on the RHS. So you need to ensure that the RHS can generate 168 separate arrays in a comma-separated list and the LHS is also a valid comma-separated list. My tutorial covers the main ways you specify comma-separated lists, so I will not repeat it here.
This means that your operation reduces down to this:
S = struct('X',cell(1,168))
S = 1x168 struct array with fields:
X
try % error
S.X = 1:168
catch ME
ME.message
end
ans = 'Scalar structure required for this assignment.'
C = num2cell(1:168);
[S.X] = C{:} % no error
S = 1x168 struct array with fields:
X
You can nest that in as many scalar structures as you wish, they make no difference.
** which you refer to using the (presumably) scalar i-index, thus the LHS refers to a scalar structure containing a nested non-scalar structure. The fact that MPDATA itself might be a non-scalar structure is completely irrelevant.
  5 Comments
Stephen23
Stephen23 on 12 Nov 2024
Edited: Stephen23 on 12 Nov 2024
"Why is that [] necessary in first place in LHS?"
By definition, because that is the syntax MATLAB uses to specify multiple arrays on the LHS. For example, this is used to return multiple outputs from a function call (note that many languages only support one output argument). Returning multiple output arguments from a function call is explained in the introductory tutorials:
"I have never used this before"
While I guess it would be possible to write code without them, doing so would be extremely restrictive: you would miss out on many many many useful output arguments, e.g. the indices from MIN, MAX, ISMEMBER, etc.
"because im assuming that there is no need for that, if that variable already is comma separated list."
Sure, it is a comma-separated list. But a comma-separated list by itself does nothing much. Why do this?:
A,B,C,D
%^^^^^^^ comma-separated list
If your goal is e.g. to display some variables then that is all you need. For fun perhaps, but otherwise not very useful. But the point of any comma-separated list is where you can use it. For example, when calling a function by providing it with multiple inputs:
fun(A,B,C,D)
% ^^^^^^^ comma-separated list
"i.e if a = [1,2,3,4]..."
Note that your example used a comma-separated list with the concatenation operator:
a = [1,2,3,4]
% ^^^^^^^ comma-separated list
"then a == [a]"
That is only one array. In general comma-separated lists refer to zero, one, or multiple arrays:
A,B,C,D
The goal of your original question was to allocate 168 arrays (to the elements of a non-scalar structure), not one array.
Sven Larsen
Sven Larsen on 12 Nov 2024
ok, I think I got it now. Thank you for your patience and great help! And yes, I use [] all the time (in min max etc) but not in context which was problem in OP.

Sign in to comment.

Products


Release

R2021a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!