Reputation: 8091
Is there a "better"(means readable and vectorized) method to use a struct with indices to generate a result struct?
# struct values are indices into b
a.foo = 2;
a.bar = 3;
b = [e pi 123 1337];
## the loopy way
for [val, key] = a
c.(key) = b(val);
endfor
disp (c)
which gives the desired result
scalar structure containing the fields:
foo = 3.1416
bar = 123
or another clumsy and almost obfuscated way:
d = cell2struct(num2cell(b([struct2cell(a){:}])'), fieldnames(a));
assert (c, d);
Upvotes: 1
Views: 90
Reputation: 22215
In theory, the lovely one-liner you're looking for is probably:
structfun (@ (x) b(x), a, 'UniformOutput', false);
However, structfun, much like its other 'fun' relatives, seems to be just syntactic sugar rather than actual vectorisation. So in fact the fastest (and arguably cleanest) method does seem to be your for loop:
Benchmark:
octave:1> a.foo = 2; a.bar = 3; b = [e pi 123 1337];
octave:2> # loop method #
> tic; for i = 1 : 100;
> for [val, key] = a; S1.(key) = b(val); end;
> end; toc
Elapsed time is 0.00160003 seconds.
octave:3> # cell2struct method #
> tic; for i = 1 : 100;
> S2 = cell2struct(num2cell(b([struct2cell(a){:}])'), fieldnames(a));
> end; toc
Elapsed time is 0.006423 seconds.
octave:4> # structfun method #
> tic; for i = 1: 100
> S3 = structfun(@ (x) b(x), a, 'UniformOutput', false);
> end; toc
Elapsed time is 0.279853 seconds.
PS. However, note that the for-loop approach will not work "as is" if you have an array of structs, whereas the structfun approach will.
Upvotes: 3