Plus d'une fois maintenant, j'ai eu besoin de générer toutes les paires possibles de deux vecteurs dans MATLAB que je fais avec pour les boucles qui occupent quelques lignes de code, c'est-à-dire.
vec1 = 1:4;
vec2 = 1:3;
i = 0;
pairs = zeros([4*3 2]);
for val1 = vec1
for val2 = vec2
i = i + 1;
pairs(i,1) = val1;
pairs(i,2) = val2;
end
end
Génère ...
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1
4 2
4 3
Il doit y avoir une meilleure façon de le faire qui est plus MATLAB'esque?
n.b. nchoosek
ne fait pas les paires inversées, c'est ce dont j'ai besoin (c'est-à-dire 2 1
aussi bien que 1 2
), Je ne peux pas simplement inverser et ajouter la sortie nchoosek
car les paires symétriques seront incluses deux fois.
Essayer
[p,q] = meshgrid(vec1, vec2);
pairs = [p(:) q(:)];
Voir la documentation MESHGRID . Bien que ce ne soit pas exactement à quoi sert cette fonction, mais si vous plissez les yeux à ce sujet, ce que vous demandez, c'est exactement ce qu'il fait.
Vous pouvez utiliser
a = 1:4;
b = 1:3;
result = combvec(a,b);
result = result'
Vous pouvez le faire en répliquant les matrices en utilisant repmat
puis en transformant le résultat en un vecteur de colonne en utilisant reshape
.
a = 1:4;
b = 1:3;
c = reshape( repmat(a, numel(b), 1), numel(a) * numel(b), 1 );
d = repmat(b(:), length(a), 1);
e = [c d]
e =
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1
4 2
4 3
Bien sûr, vous pouvez vous débarrasser de toutes les variables intermédiaires de l'exemple ci-dessus.
Une autre solution pour la collecte:
[idx2, idx1] = find(true(numel(vec2),numel(vec1)));
pairs = [reshape(vec1(idx1), [], 1), reshape(vec2(idx2), [], 1)];
Vous pouvez utiliser des opérations matricielles simples, par exemple dans
x = [3,2,1];
y = [11,22,33,44,55];
v = [(ones(length(y),1) * x)(:), (ones(length(x), 1) * y)'(:)]
Edit: c'est la syntaxe Octave, MATLAB ressemblera à ceci:
x = [3,2,1];
y = [11,22,33,44,55];
A = ones(length(y),1) * x;
B = (ones(length(x), 1) * y)';
v = [A(:) B(:)]
dans les deux cas, le résultat sera
v =
3 11
3 22
3 33
3 44
3 55
2 11
2 22
2 33
2 44
2 55
1 11
1 22
1 33
1 44
1 55
Voici une façon plus MATLAB'esque de trouver les combinaisons. Celui-ci peut également être facilement étendu à plus de 2 vecteurs (et aussi à des combinaisons non numériques):
v1 = 1: 1: 3;
v2 = 11: 11: 44;
v3 = 111:111:555;
dimensions = cellfun(@numel, {v1,v2,v3});
[i1,i2,i3] = ind2sub(dimensions, 1:prod(dimensions));
combinations = [v1(i1); v2(i2); v3(i3)]'
À partir de la version R2015a, vous pouvez le faire en utilisant repelem
et repmat
:
>> vec1 = 1:4;
>> vec2 = 1:3;
>> pairs = [repelem(vec1(:), numel(vec2)) ...
repmat(vec2(:), numel(vec1), 1)]
pairs =
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1
4 2
4 3
Ce type de solution évite les variables intermédiaires supplémentaires requises par certaines des autres solutions (telles que celles basées sur meshgrid
), ce qui pourrait entraîner des problèmes de mémoire pour des vecteurs plus grands.
Ce que vous cherchez, c'est le produit cartésien
cartprod est la fonction qui l'implémente. Vous pouvez le trouver dans le package d'algèbre linéaire, vous devez donc faire:
>> pkg install -forge linear-algebra
>> pkg load linear-algebra
>> sortrows(cartprod(1:4,1:3))
ans =
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1
4 2
4 3