2016-01-25 13 views
6

Qual è un modo conciso per iterare su coppie di elementi non ordinati in unordered_set?Come eseguire iterazioni su coppie non ordinate all'interno di un set non ordinato?

(Quindi ordine non ha importanza e gli elementi dovrebbe essere diverso)

esempio {1, 2, 3} => (1, 2) (2, 3) (1, 3)

I miei tentativi iniziali erano qualcosa di simile

for (i = 0; i < size - 1; i++) { 
    for (j = i + 1; j < size; j++) { 
    ... 
    } 
} 

Ma questo non è super-conveniente con iteratori.

+3

@arainone Possibile caso di "Non ho letto la domanda". – orlp

+0

Quindi per alcuni set 'X' vuoi' {(x1, x2) | x1, x2 ∈ X, x1 \t ≠ x2} '? L'ho letto bene? –

+0

Se la sovrapposizione ('[0,1], [1,2] [2,3] ...') o vuoi '[0,1], [2,3] [4,5] .. .'? – NathanOliver

risposta

7

Questo dovrebbe funzionare, dato un std::unordered_sets:

auto set_end = s.end(); 
for (auto ai = s.begin(); ai != set_end; ++ai) { 
    for (auto bi = std::next(ai); bi != set_end; ++bi) { 
     // *ai, *bi 
    } 
} 

Questo è fondamentalmente l'iteratore equivalente di quanto segue in numeri interi:

for (int i = 0; i < n; ++i) { 
    for (int j = i + 1; j < n; ++j) { 
     // i, j 
    } 
} 
+0

Suggerisco 'std :: for_each' su un ciclo' for' vecchio stile. – caps

+2

@caps 'std :: for_each' non fornisce iteratori e il ciclo interno dipende dall'iteratore del ciclo esterno. – orlp

+0

Proprio per curiosità, c'è una ragione per cui hai usato 'set_end' invece di' s.end() 'nei loop? – erip

1

Ecco la soluzione di orlp in forma semi-generiche.

template<typename ForwardIterator, typename DestItr> 
auto cartesian_product(ForwardIterator b, ForwardIterator e, DestItr d) -> DestItr { 
    using std::next; 
    using std::for_each; 
    for (; b != e; ++b) { 
     for_each(next(b), e, [&](auto right){ 
      *d++ = std::make_tuple(*b, right); 
     }); 
    } 
    return d; 
} 

template<typename ForwardRange, typename DestItr> 
auto cartesian_product(ForwardRange r, DestItr d) -> DestItr { 
    using std::begin; 
    using std::end; 
    return cartesian_product(begin(r), end(r), d); 
} 

Live on Coliru.

Si potrebbe, ovviamente, renderlo più generico avendo sovraccarichi per funtori personalizzato da utilizzare al posto del make_tuple e l'operatore di assegnazione. Gli algoritmi di libreria standard tendono a farlo. Se scrivessi questo per una biblioteca, probabilmente lo farei anche io.

+0

Non nominare questo 'cartesian_product', perché questo è decisamente __not__ il prodotto cartesiano. Sono le 2 combinazioni di un set con se stesso. – orlp

+0

Hmm. Qualcosa come ... 'self_combination'? 'Self_permutations_combination'? – caps

Problemi correlati