How to generate all combinations of N struct vectors.

16 vues (au cours des 30 derniers jours)
N/A
N/A le 26 Mai 2020
While combvec and allcomb seems to both give all combinations of numerical vectors (no idea why there are two functions that does the same thing), neither work for structure vectors. Given an arbitrary number N of structure vectors I would like to generate all possible combinations of them. My end goal is to then merge them (in order to generate combinatorial conditions for a simulation (which I found can be done via https://mathworks.com/matlabcentral/fileexchange/38821-structure-overwrite-and-merge).
An easy way to do this is via nested for loops of course, but that quickly gets out of hand as the number of struct vectors increase, thus I'm looking for a function to do this for an arbitrary number of struct vectors.
Note! Not all structs contain all members. This would leave me to believe I would probably need to use cell arrays to handle the disimilar structures,
a_conditions(1).a = 5;
a_conditions(2).a = 9;
b_conditions(1).b = 2;
b_conditions(1).bextra = "a string";
b_conditions(2).b = 98;
b_conditions(1).bextra = "another string";
b_conditions(3).b = 22;
b_conditions(3).bextra = "something else";
% And here there will be c_conditions, etc.
% allcomb will not work here, as stated above
for conds = allcomb(a_conditions, b_conditions, ...)
combined = [combined merge(conds(1:end))] % using a modified variant of the merge function from the link above
end
% combined should now contain:
combined(1).a = 5;
combined(1).b = 2;
combined(1).bextra = "a string";
combined(2).a = 5;
combined(2).b = 98;
combined(2).bextra = "another string";
combined(3).a = 5;
combined(3).b = 22;
combined(3).bextra = "something else";
combined(4).a = 9;
combined(4).b = 2;
combined(4).bextra = "a string";
% and so on
As can be seen, because I need to deal with structures containing non-trivial data types, including scalars, matrices, strings etc, and where some of the conditions might affect multiple variables, I cannot see a reasonable way to rewrite it in terms of allcomb or combvec. Is there anything existing, or do I need to roll my own function for this?

Réponses (1)

Stephen23
Stephen23 le 26 Mai 2020
Modifié(e) : Stephen23 le 26 Mai 2020
It is much simpler when those structures are stored in one cell array, e.g.:
C{1}(1).a = 5;
C{1}(2).a = 9;
C{2}(1).b = 2;
C{2}(1).bextra = 'a string';
C{2}(2).b = 98;
C{2}(2).bextra = 'another string';
C{2}(3).b = 22;
C{2}(3).bextra = 'something else';
Then merging them together in all combinations can be achieved like this:
X = cellfun(@(s)1:numel(s),C,'uni',0);
[X{:}] = ndgrid(X{:});
T = cellfun(@(c,x)c(x),C,X,'uni',0);
D = cellfun(@struct2cell,T,'uni',0);
F = cellfun(@fieldnames,T,'uni',0);
D = vertcat(D{:});
F = vertcat(F{:});
S = cell2struct(D,F,1);
Giving:
>> S
S =
2x3 struct array with fields:
a
b
bextra
Checking a few elements of the output structure:
>> S(1)
ans =
a: 5
b: 2
bextra: 'a string'
>> S(6)
ans =
a: 9
b: 22
bextra: 'something else'
  2 commentaires
N/A
N/A le 29 Mai 2020
While it works for the simple example here, it has some minor issues for my full use case, that my example did not show (as I did not realise those would be potential issues):
  • If any of the condition groups contains just one condition (for example, if I want to only run a subset of the simulations for debugging purposes and I have commented out the other alternatives).
  • If there is any overlap between the members in the different groups. I was imagining later groups to overwrite earlier groups.
While I can certainly work around these, if you happen to know a quick and easy fix to avoid that, it would be much appreciated.
Tiago Pomella Lobo
Tiago Pomella Lobo le 8 Août 2023
Modifié(e) : Tiago Pomella Lobo le 8 Août 2023
To avoid issues with structs built from a set of scalars plus a single final cell array, take a look at this contribution.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Structures dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by