I have a struct with several fieldnames, each of them is again a struct and has a fieldname "P". This "P" is an array.
I want to calculate the sum of all "P "s like:
s.s1.P = (1:20).'; % For simplicity I have assigned dummy values to the "P "s.
s.s2.P = (1:20).';
s.s3.P = (1:20).';
% ...
result = s.s1.P + s.s2.P + s.s3.P % + ...
I have already a solution with a for loop:
field = fieldnames(s);
result = zeros(size(s.(field{1}).P));
for i = 1:length(field)
result = result +s.(field{i}).P;
end
I also tried to use "structfun" but were not able to get this result.
Is it possible to calculate this problem with "structfun" or another function or is the for loop the final solution for this problem?

1 comentario

Stephen23
Stephen23 el 4 de Sept. de 2023
Rather than forcing pseudo-indices into fieldnames you should simply use a structure array, as dpb showed.

Iniciar sesión para comentar.

 Respuesta aceptada

Bruno Luong
Bruno Luong el 4 de Sept. de 2023
Editada: Bruno Luong el 4 de Sept. de 2023
Single line (work for fields with struct NOT objects of class, struct is NOT some sort of class)
s.s1.P = (1:20).'; % For simplicity I have assigned dummy values to the "P "s.
s.s2.P = (1:20).';
s.s3.P = (1:20).';
sum([cat(1,struct('sx',struct2cell(s)).sx).P],2)
ans = 20×1
3 6 9 12 15 18 21 24 27 30

Más respuestas (2)

dpb
dpb el 4 de Sept. de 2023
Editada: dpb el 4 de Sept. de 2023
The problem of using sequentially-named fields in the struct instead of an array of struct; there's no good way to process the resulting variables or struct fields programmatically when do so.
structfun applies the function to each field of a scalar struct so it isn't the tool for the purpose here, anyway, you're trying to process across fields, not within each. And, arrayfun is for an array but you didn't use an array to hold the similar data, you chose to use multiple fields instead. A 2D array would have been an alternate choice that could have handled easily...
s.P = (1:20).';
s.P = [s.P (1:20).'];
s.P = [s.P (1:20).'];
result = sum(s.P,2)
result = 20×1
3 6 9 12 15 18 21 24 27 30
Or, alternatively, as a struct array
s.P = (1:20).';
s(2).P = (1:20).';
s(3).P = (1:20).';
result = sum([s.P],2)
result = 20×1
3 6 9 12 15 18 21 24 27 30

7 comentarios

Julian
Julian el 4 de Sept. de 2023
Earlier I solved it with a cell.
I originally forgot to say that my inner struct is really a custom class, which is kind of like a struct.
The second variant is interesting for me and I will probably implement it, since I can hopefully save the cellfun in the later code flow.
Bruno Luong
Bruno Luong el 4 de Sept. de 2023
Editada: Bruno Luong el 4 de Sept. de 2023
A class? But you said in the question "I also tried to use "structfun" but were not able to get this result" How can you even possible use structfun on a class???
Julian
Julian el 4 de Sept. de 2023
Editada: Julian el 5 de Sept. de 2023
Sorry I am working for too long.
I meant an object, an instance of a class.
You can use "structfun" for structs (and for objects, because structs are special Matlab objects.The second part of this sentence is wrong)
Bruno Luong
Bruno Luong el 4 de Sept. de 2023
"structs are special Matlab objects"
No, this is incorrect.
Paul
Paul el 4 de Sept. de 2023
structfun can be used on class objects?
Bruno Luong
Bruno Luong el 4 de Sept. de 2023
Editada: Bruno Luong el 4 de Sept. de 2023
No
D=delaunayTriangulation(rand(10,2))
D =
delaunayTriangulation with properties: Points: [10×2 double] ConnectivityList: [12×3 double] Constraints: []
structfun(@(D)D.Points, D)
Error using structfun
Inputs to STRUCTFUN must be scalar structures.
Sorry my first remark on structfun on class is not applicable int the present context, since s is still a struct with 3 fields. structun can be applied on s.
Julian
Julian el 5 de Sept. de 2023
Yes structfun was used on s, a struct and it's not posible to use structfun on class objects.

Iniciar sesión para comentar.

Bruno Luong
Bruno Luong el 4 de Sept. de 2023
Editada: Bruno Luong el 4 de Sept. de 2023
Honestly I prefer the for-loop
s.s1.P = (1:20).'; % For simplicity I have assigned dummy values to the "P "s.
s.s2.P = (1:20).';
s.s3.P = (1:20).';
c = struct2cell(structfun(@(sf) sf.P, s, 'UniformOutput', false));
sum(cat(2,c{:}),2)
ans = 20×1
3 6 9 12 15 18 21 24 27 30

2 comentarios

dpb
dpb el 4 de Sept. de 2023
Given the already bad idea of having created the sequentially-named fields, agree, the for loop is the way; as your example shows, to do anything else gets far too convoluted and undoubtedly would be slower besides.
At least with struct fields, one can programmatically access them w/o the eval abomination.
Julian
Julian el 4 de Sept. de 2023
Thanks for the solution.
Unfortunately, I already came up with this, but I didn't like this huge nesting of functions either.
I understand why you would prefer the for-loop.

Iniciar sesión para comentar.

Categorías

Más información sobre Data Type Identification en Centro de ayuda y File Exchange.

Productos

Versión

R2023a

Etiquetas

Preguntada:

el 4 de Sept. de 2023

Comentada:

el 5 de Sept. de 2023

Community Treasure Hunt

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

Start Hunting!

Translated by