Does struct manipulation work in place when using arrayfun on an array of structs?

2 views (last 30 days)
I would like to better understand how arrays of structured data are handled when they are manipulated using arrayfun. I've created a minimal example below to show the kind of situation I'm looking at. In this example, I'm applying a function to each struct in an array of structs using arrayfun to manipulate the structures by adding an additional field. Does this code work "in place" on the structs in the array, only allocating new memory for the new field? If this will copy the structures (or the entire array) as the fields are added, then it seems better to use a loop than arrayfun. I'd appreciate any insight into how the memory is managed during this kind of operation.
s = struct("x", {1, 2, 3});
s = arrayfun(@update, s);
function s = update(s)
s.y = s.x^2;
end

Accepted Answer

Matt J
Matt J on 19 Apr 2024
Edited: Matt J on 19 Apr 2024
It does indeed appear that with arrayfun (unlike loops), pre-existing field contents get deep-copied to a new memory address (as indicated by pr in the results below):
s= struct("x", {1:5,2:6,3:7});
u=s; for i=1:numel(s), u(i).y=u(i).x.^2; end %loop copy
v=arrayfun(@update, s); %arrayfun copy
format debug
s(3).x
ans =
Structure address = 1ab51ab5120
m = 1
n = 5
pr = 1ab6b9a1d80
3 4 5 6 7
u(3).x
ans =
Structure address = 1ab51ab5120
m = 1
n = 5
pr = 1ab6b9a1d80
3 4 5 6 7
v(3).x
Structure address = 1ab4d81f7c0
m = 1
n = 5
pr = 1ab6d5f5500
3 4 5 6 7
function s = update(s)
s.y = s.x.^2;
end
  3 Comments
Steven Lord
Steven Lord on 19 Apr 2024
Your function may be simpler and faster than arrayfun, but it doesn't do everything arrayfun does.
x = [1:5 -1];
y = arrayfun(@realsqrt, x, ErrorHandler = @(varargin) NaN)
y = 1x6
1.0000 1.4142 1.7321 2.0000 2.2361 NaN
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
z = arrayfun(@ones, x, UniformOutput = false)
z = 1x6 cell array
{[1]} {2x2 double} {3x3 double} {4x4 double} {5x5 double} {0x0 double}
y2 = myArrayfun(@realsqrt, x)
Realsqrt produced complex result.

Error in solution>myArrayfun (line 9)
C(i)=fun(A(i));
It also lacks the capability to handle non-uniform outputs from the function (the 'UniformOutputs' name-value argument, see the creation of z above.) There are some circumstances where you may not need the full level of flexibility of arrayfun, and in those cases you can beat the performance of arrayfun.
function C=myArrayfun(fun,A)
C=repmat( fun(A(1)), size(A) );
for i=2:numel(C)
C(i)=fun(A(i));
end
end
Matt J
Matt J on 19 Apr 2024
Edited: Matt J on 20 Apr 2024
but it doesn't do everything arrayfun does.
Yes, for the purposes of this example that's true, but I can't see why any of those additional features explain why deep copying of all the input array data is done by the native arrayfun. I feel like I could add those features to my version without the deep copying, and still see a performance benefit.

Sign in to comment.

More Answers (0)

Categories

Find more on Structures in Help Center and File Exchange

Products


Release

R2024a

Community Treasure Hunt

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

Start Hunting!