¿Cómo generar todos los pares de dos vectores en MATLAB usando código vectorizado?

Más de una vez ahora he necesitado generar todos los pares posibles de dos vectores en MATLAB, lo cual hago con los bucles que ocupan unas pocas líneas de código, es decir,

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 

Genera …

 1 1 1 2 1 3 2 1 2 2 2 3 3 1 3 2 3 3 4 1 4 2 4 3 

Debe haber una mejor manera de hacer esto que es más MATLAB’esque?

nb nchoosek no hace los pares invertidos que es lo que necesito (es decir, 2 1 así como 1 2 ), no puedo simplemente invertir y anexar la salida nchoosek porque los pares simétricos se incluirán dos veces.

Tratar

 [p,q] = meshgrid(vec1, vec2); pairs = [p(:) q(:)]; 

Ver la documentación de MESHGRID . Aunque esto no es exactamente para lo que sirve esa función, pero si entiendes que es divertido, lo que estás pidiendo es exactamente lo que hace.

Puedes utilizar

 a = 1:4; b = 1:3; result = combvec(a,b); result = result' 

Otra solución para la colección:

 [idx2, idx1] = find(true(numel(vec2),numel(vec1))); pairs = [reshape(vec1(idx1), [], 1), reshape(vec2(idx2), [], 1)]; 

Puedes hacerlo replicando las matrices usando repmat y luego convirtiendo el resultado en un vector de columna usando 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 = [cd] 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 

Por supuesto, puede deshacerse de todas las variables intermedias del ejemplo anterior.

Aquí una forma más exacta de MATLAB para encontrar las combinaciones. Este también se puede extender fácilmente a más de 2 vectores (y también combinaciones no numéricas):

 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)]' 

Puede usar operaciones planas antiguas, por ejemplo, en

 x = [3,2,1]; y = [11,22,33,44,55]; v = [(ones(length(y),1) * x)(:), (ones(length(x), 1) * y)'(:)] 

Editar: esta es la syntax de Octave, MATLAB se verá así:

 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(:)] 

en ambos casos, el resultado será

 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 

Lo que estás buscando es el producto cartesiano

cartprod es la función que lo implementa. Puede encontrarlo en el paquete de álgebra lineal, por lo que tendría que hacer:

  >> 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