если вы не знаете, сколько у вас «групп», я полагаю, у вас есть хотя бы некоторая коллекция из них? т.е. массив / вектор всех ваших векторов?
если так, вот общее представление о том, что будет работать
void iterateAllCombinations(array_of_groups, current_group_index,temp_result,callback_function)
{
current_group = array_of_groups[current_group_index]
for each element in current_group
{
temp_result[current_group_index]=element
if current_group_index>0
iterateAllCombinations(array_of_groups,current_group_index-1,temp_result,callback_function)
else
callback_function(temp_result)
}
}
this would be called in some fashion like:
iterateAllCombinations(my_groups,my_groups.length-1,new vector[my_groups.length],&do_something_with_array)
Основное объяснение того, что происходит:
когда вы вызываете функцию, она начинает проходить через каждый элемент в «верхней» группе (последний в array_of_groups). Если кроме «верхней» группы будет больше групп, она вызовет ту же функцию, пропустив текущие элементы и попросив ее просмотреть следующую группу.
Этот следующий уровень вниз начнет проходить через каждый предмет и будет вести себя одинаково. Это продолжается до тех пор, пока вы не попадете в нижнюю группу, где вместо вызова другого уровня он передаст сбор всех результатов в вашу функцию обратного вызова, которая будет их использовать.
Когда нижний уровень прошел через все элементы, он вернется к следующему уровню, который все еще находится в цикле «для каждого». следующий уровень вверх перейдет к следующему пункту и вызовет нижний уровень, который начнется с начала. это продолжается до тех пор, пока в конечном итоге даже «верхний» уровень не пройдет через каждый элемент.
Это псевдокод, особенности меняются в зависимости от вашего языка.
«временный результат» может быть объявленным и выделенным предварительным массивом (как я показываю в псевдокоде), или это может быть стек, который передается перед каждым рекурсивным вызовом и извлекается после, или это может быть массив / вектор, который вы копируете и добавляете перед каждым рекурсивным вызовом. Вы могли бы даже иметь связанный список, где каждый узел просто сохранялся бы в кадре стека для этого вызова функции, и вам просто нужно было бы передать указатель «родителя» на следующий уровень вниз.
Если у вас есть одна конкретная вещь, которую вы хотите сделать, вы можете заменить 'callback_function' этой конкретной вещью. Или, если ваш язык это позволяет, вы можете использовать это как итератор / генератор и позволить этому «обратному вызову» быть неявным
Если вы действительно ненавидите рекурсивный код, вы можете написать то же самое, что и цикл while, но гораздо проще написать его как рекурсивную функцию.