iterating over multiple structures using structfun

Suppose I have data organized in multilayer structures, where fields of each structure contain data of an individual animal, such as the example below:
data1.animal1.exp1 = 'someData';
data1.animal1.exp2 = 'someData';
data1.animal2.exp1 = 'someData';
...
and suppose I have several different data organized in the same way:
data2.animal1.exp1 = 'someOtherData';
data2.animal1.exp2 = 'someOtherData';
...
The individual structures (data1 / data2) contain complementary data. Now I want to be able to run functions on each element of the data using a combination of cellfun and structfun functions. The reason for this is that I want to keep the data hierarchy consistent.
I am able to do this:
NewData = structfun(@(x) structfun(@myFunction1, x, 'UniformOutput', false), data1, 'UniformOutput', false);
Then I want to run a different function in the same fashion, however that function takes two arguments:
NewData = structfun(@(x,y) structfun(@(x,y) myFunction2(x, y), x, y, 'UniformOutput', false), data1, data2, 'UniformOutput', false);
This does not work, because 'STRUCTFUN only iterates over the fields of one structure.' Is there a way how multiple arguments can be passed into a structfun?
I am able to do what I want in a loop, but I'm a bit obsessed with single line solutions because of convenience and readability of my code.
Thanks for your help.

3 Comments

You could also write your own wrapper for structfun that allows you use multiple inputs by using a loop.
You should be aware that convoluted single-line calls can be much harder to read than a loop, which will be easy to understand. You should also be aware of the performance penalty: cellfun, structfun and arrayfun hide the loop at a cost. This cost is both in runtime and in the time required to understand your code.
You only have to take a look at Cody solution to see what price you pay for compact code.
Thanks for your answer Rik. Do you have any specific suggestion on how such a wrapper should look like?
Since you want to replicate part of the functionality of structfun you will probably need fieldnames, but otherwise I don't understand what you want well enough to suggest an implementation. That is why I posted my suggestion as a comment, not as answer.

Sign in to comment.

 Accepted Answer

fnames = fieldnames(data1);
temp = cellfun(@(FN) myFunction2(data1.(FN), data2.(FN)), fnames, 'uniform', 0);
result = cell2struct(temp, fnames, 1); %might need ,2) instead of ,1)

More Answers (0)

Categories

Community Treasure Hunt

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

Start Hunting!