Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

How to make an anonymous function for variable amount of input data

Asked by Dan K on 7 Feb 2013

Hi all,

I'm trying to generate an anonymous function where I pass in an array of structures and convert it to a structure of arrays (possibly offsetting the indices for each of the inputs). I've been doing it so far using an anonymous function, but I'm trying to figure out how to generalize it.

Here's what I've got so far:

            Sync = @(x,fna) [x(1).(fna)(shape_params.indices{1}),...
              x(2).(fna)(shape_params.indices{2})];

So when I call it I give it the array of structures (x), and the field name (fna) that I want to create the output array of. shape_param.indices is a cell array that tells me which entries I want from each of the entries in the array of structs.

For example:
XX(1).a = (1:10)';
XX(2).a = (2:11)';
shape_params.indices{1} = (2:5)';
shape_params.indices{2} = (1:4)';
YY.a = Sync(XX,'a')
should give me:
YY.a = [2,2;3,3;4,4;5,5];

I can define Sync to accomodate the number of entries in XX by just creating a switch. But now I need to generalize it, since I don't want to make a switch statement that has up to 16 varieties.

Any suggestions on how I can do it, for an unknown number of vectors that I'm combining?

Thanks, Dan

1 Comment

Dan K on 7 Feb 2013

I should mention: XX and YY are actually objects, not structures, although I don't believe that changes anything.

I've gotten as far as being able to create a sub-anonymous function that lets me choose which entry I want:

extract_one = @(x,fna,n) x(n).(fna)(shape_params.indices{n});

But if I try:

YY = [extract_one(XX,'a',1:n)] 
I get:
Scalar index required for this type of multi-level indexing.
Dan K

Products

2 Answers

Answer by Cedric Wannaz on 7 Feb 2013
Accepted answer

It is difficult to implement conditional statements in anonymous functions (it requires a test function); why do you want to use an anonymous function? Couldn't you simply do something like the following?

 data = [XX(:).a] ; idx = [shape_params.indices{:}] ;
 YY.a = cell2mat(arrayfun(@(c)data(idx(:,c),c), 1:size(data,2), ...
                 'UniformOutput', false)) ;

5 Comments

Dan K on 7 Feb 2013

Again, we'll have the same problem since size(XX(1).a) may not equal size(XX(2).a) I will have to think about the possibility of creating a non-anonymous function (although I've been trying to limit the number of methods that I create for the object). Either way, thanks for the input.

Dan

Cedric Wannaz on 7 Feb 2013

Actually no, look at the way I build data; it is a cell array now. I am calling arrayfun on an array of indices and not on data; this might be what brings a bit of confusion. I tested it with XX(1).a=(21:30).' and XX(2).a=(22:100).' and it worked.

Dan K on 8 Feb 2013

Cedric,

I see the difference now. Yes, it does work. It's not quite as "sexy" as doing it in a nicely contained anonymous function, but it serves the purpose. I welcome additional comments, but I'm going to accept this answer.

Cedric Wannaz
Answer by Tucker McClure on 8 Feb 2013

Not sure I exactly understand you, Dan, but is this what you're trying to do? This is the anonymous function version. You might want to consider making a private method instead, but if it needs to be anonymous, then this seems to get the job done.

f = @(objects, indices) ...                         % Function header
    arrayfun(@(k) objects(k).field(indices{k}), ... % Get indices of obj(k)
             1:length(objects), ...                 % for k = 1:n.
             'UniformOutput', false);               % Output in cells.
my_struct_array(1).field = (1:10)';
my_struct_array(2).field = (2:2:20)';
my_indices = {1:5, 6:10};
f(my_struct_array, my_indices)

Also, if the indices are guaranteed to be the same length, then you could output to a matrix instead of a cell array by adding a cell2mat(...) around the arrayfun(...).

Hope that helps.

0 Comments

Tucker McClure

Contact us