2011-09-16 21 views
43

Più di una volta ora ho bisogno di generare tutte le possibili coppie di due vettori in MATLAB, che faccio con i cicli for che occupano una fiera poche righe di codice cioèCome generare tutte le coppie da due vettori in MATLAB usando un codice vettoriale?

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 

Ci deve essere un modo migliore per fare ciò che è più MATLAB?

n.b. nchoosek non esegue le coppie invertite che è quello che mi serve (ad esempio 2 1 e 1 2), non è possibile invertire e aggiungere l'output nchoosek perché le coppie simmetriche verranno incluse due volte.

+2

possibile duplicato di [Matlab - Genera tutte le possibili combinazioni degli elementi di alcuni vettori] (http://stackoverflow.com/questions/4165859/matlab-generate-all-possibile-combinazioni-degli-elementi-di-some-vettori) – Amro

risposta

86

Prova

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

Vedere le MESHGRID documentation. Anche se questo non è esattamente ciò che questa funzione è, ma se si strizza l'occhio a ciò che è divertente, quello che stai chiedendo è esattamente quello che fa.

+1

È fantastico. Conoscevo sia 'meshgrid' che serializzazione dei vettori 2d ma non ho mai considerato di usarli in questo modo. – Brendan

3

È possibile eseguire la replica replicando le matrici utilizzando repmat e quindi trasformando il risultato in un vettore di colonna utilizzando 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 

Naturalmente, è possibile eliminare tutte le variabili intermedie dell'esempio precedente.

3

Un'altra soluzione per la raccolta:

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

+1: ho eliminato la mia soluzione, mi piace di più la tua. Mi sono preso la libertà di correggerlo, per ottenere le combinazioni di 'vec1' e' vec2'. –

+0

@EitanT: non c'è bisogno di rimodellare. Gli indici da 'find' dovrebbero sempre essere i vettori di colonna, così come' vec1 (idx1) 'ecc. – yuk

+0

Penso che sia necessario rimodellare. Dato che 'idx1' è un vettore (non importa se riga o colonna), se' vec1' è un vettore riga allora 'vec1 (idx1)' sarà anche un vettore riga. Lo stesso vale per 'vec2'. –

11

È possibile utilizzare

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

Si noti che ciò richiede la casella degli strumenti Rete neurale. Per quelli che ce l'hanno sembra essere la soluzione migliore. –

+0

Come questo meglio della soluzione accettata, in quanto generalizza a più vettori. – neuronet

+1

@neuronet Una risposta tardiva lo so, ma vale la pena che i futuri visitatori sappiano che questo è * molto * lento rispetto alla soluzione accettata per i vettori di grandi dimensioni. – Wolfie

0

Quello che state cercando è il cartesian product

cartprod è la funzione che lo implementa. Lo si può trovare nel pacchetto lineare algebra così si avrebbe bisogno di fare:

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

Per quello che vale, una funzione che afferma di fare la stessa cosa è disponibile anche su [MATLAB File exchange] (http://www.mathworks.com/matlabcentral/fileexchange/5475-cartprod--cartesian-product-of- multiple-set). – mikkola

1

Qui un modo più MATLAB'esque per trovare le combinazioni. Questo può anche essere facilmente esteso per più di 2 vettori (e combinazioni anche non numerici):

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

È possibile utilizzare le operazioni semplici matrici vecchi, ad esempio in

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

Edit: questa è la sintassi Octave, MATLAB sarà simile a questo:

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

in entrambi i casi, risultato sarà

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

Questa non è una sintassi MATLAB valida. – gnovice

+0

@gnovice grazie, mio ​​male. Ho risolto la sintassi. – jihor

Problemi correlati