2016-01-25 2 views
6

Что такое краткий способ итерации по неупорядоченным парам элементов в unordered_set?Как перебирать неупорядоченные пары внутри unordered_set?

(Так порядок не имеет значения, и элементы должны быть различными)

например, {1, 2, 3} => (1, 2) (2, 3) (1, 3)

Мои первые попытки были чем-то вроде

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

Но это не супер-удобно с итераторы.

+3

@arainone Возможный случай: «Я не читал вопрос». – orlp

+0

Итак, для некоторого набора 'X' вы хотите' {(x1, x2) | x1, x2 ∈ X, x1 \t ≠ x2} '? Правильно ли я это прочитал? –

+0

Если перекрытие ('[0,1], [1,2] [2,3] ...') или вы хотите '[0,1], [2,3] [4,5] .. .'? – NathanOliver

ответ

7

Это должно работать, дается 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 
    } 
} 

В основном это итератор эквивалент следующих в целых числах:

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

Я бы предложил 'std :: for_each' над старомодным циклом' for'. – caps

+2

@caps 'std :: for_each' не дает итераторов, а внутренний цикл зависит от итератора внешнего цикла. – orlp

+0

Как любопытство, есть ли причина, по которой вы использовали 'set_end' вместо' s.end() 'в циклах? – erip

1

Вот решение orlp в полу-родовой форме.

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.

Вы могли бы, конечно, сделать его более универсальным, имея перегрузки для пользовательских функторов использовать вместо make_tuple и оператора присваивания. Стандартные библиотечные алгоритмы имеют тенденцию делать это. Если бы я написал это для библиотеки, я бы, наверное, так поступил.

+0

Не называйте это 'cartesian_product', потому что это определенно __not__ декартово произведение. Это две комбинации набора с самим собой. – orlp

+0

Хм. Что-то вроде ... 'self_combination'? 'Self_permutations_combination'? – caps

Смежные вопросы