Copy the values of multiple fields in a structure to another structure at once

64 views (last 30 days)
Hello,
I want to copy the values of multiple fields in a structure to another structure at once (without loop). For example, suppose the following empty structure.
A.SM = []; p = repmat(A, 3, 1); % 3 is not fixed
Now, I want to copy the contents of another structure which is as follows:
X(1).SM(:)
ans =
4 0 5 0
1 0 1 0
ans =
5 3 0 4
1 1 0 2
ans =
5 4 0 3
2 1 0 1
"p.SM = X(1).SM" does not work.
Many thanks for your help!
  4 Comments
Stephen23
Stephen23 on 6 Jun 2019
Edited: Stephen23 on 6 Jun 2019
"..suppose the following empty structure..."
Neither of the following structures are empty:
  • A has size 1x1
  • p has size 3x1
"without loop"
Using a loop will be simple and perfectly efficient. There is no point in avoiding one here.
Jan
Jan on 6 Jun 2019
@Amirhossein Moosavi: I do not know a method to create a variable, which creates this:
X(1).SM(:)
ans =
4 0 5 0
1 0 1 0
ans =
5 3 0 4
1 1 0 2
ans =
5 4 0 3
2 1 0 1
Please post exactly, what your inputs are and what the wanted result for the "copy" procedure is. Currently I guess, that the optimal solution is:
p = X(1);
but again, I do not understand, what your X(1) is.

Sign in to comment.

Accepted Answer

Walter Roberson
Walter Roberson on 6 Jun 2019
Edited: Walter Roberson on 6 Jun 2019
To do it without a loop, you would have a small number of choices:
  1. arrayfun() subsasgn . This can be used even when not all of p is being written to. It is rather obscure and not recommended. In nearly any case you would consider using subsasgn this way, any time efficiency you might gain would be outweighed by the cost of figuring out how to write the code, and debugging the code, and documenting it thoroughly. And arrayfun() is, except for some obscure cases that only Jan seems to ever use, slower than a loop
  2. In the case where all of p is being replaced, p = struct('SM', {X(1).SM}); This kind of approach can be useful and efficient in the situations in which it applies.
  3. struct2cell(p) and struct2cell(X(1).SM) and replace parts of the p converted cell with that, and then cell2struct() the result. This has a fair overhead.
  4. You might be able to rig something with setfield()
Typically the most efficient code for this kind of purpose is a loop, which also has the advantage of being really easy to read and debug.
Note: X(1).SM cannot possibly have the output you show. You would need to have one more layer of field name, or else X would have to be a non-scalar array, in which case you would be looking at X(:).SM

More Answers (2)

Bjorn Gustavsson
Bjorn Gustavsson on 6 Jun 2019
Maybe there could be faster solutions - but regardless somewhere looping over the fields will have to occur, and unless this is an explicitly proven bottle-neck of the code (checked with profile), just get it to work...
This is my old function:
function S_out = merge_fields(S1,S2,field_names)
% MERGE_FIELDS - Merge all or some fields of S2 into S1.
%
% Calling:
% S_out = merge_fields(S1,S2,field_names)
% Input:
% S1 - struct that fields in S2 will be copied to
% S2 - struct whos fields will be copied to S1
% field_names - cell or string-array with names of fields to copy from S2
% to S1, optional input
% Output:
% S_out - struct with all or selected fields from S2 copied into S1
% Copyright Björn Gustavsson 2011-06-28, <bjorn.gustavsson@irf.se>
% This is free software, licensed under GNU GPL version 2 or later
S_out = S1;
fields2 = fieldnames(S2);
if nargin > 2
fields2 = intersect(field_names,fields2);
end
for curr_field = fields2(:)',
S_out = setfield(S_out,curr_field{:},getfield(S2,curr_field{:}));
end
HTH

Jan
Jan on 6 Jun 2019
Edited: Jan on 6 Jun 2019
Maybe you mean:
A.SM = [];
p = repmat(A, 3, 1);
B.SM = 1:5;
p2 = repmat(B, 3, 1);
[p.SM] = deal(p2.SM)
Or with a loop:
for k = 1:numel(p)
p(k).SM = p2(k).SM;
end

Tags

Community Treasure Hunt

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

Start Hunting!