Groovy имеет встроенную функцию сбора combinations()
, которая генерирует все возможные комбинации из списка списков элементов.
Пример использования:
assert [['a', 'b'],[1, 2, 3]].combinations() == [['a', 1], ['b', 1], ['a', 2], ['b', 2], ['a', 3], ['b', 3]]
Вы можете просто вызвать этот метод на values
из исходного сценария:
def values = [[1,2,3], [4,5],[6,7,8,9]]
def expected = [[1,4,6],[1,4,7],[1,4,8],[1,4,9],[1,5,6],[1,5,7],[1,5,8],[1,5,9],[2,4,6],[2,4,7],[2,4,8],[2,4,9],[2,5,6],[2,5,7],[2,5,8],[2,5,9],[3,4,6],[3,4,7],[3,4,8],[3,4,9],[3,5,6],[3,5,7],[3,5,8],[3,5,9]]
def result = values.combinations()
assert ((expected as Set) == (result as Set))
Однако, если вы действительно хотите реализовать этот алгоритм самостоятельно, вы можетереализовать довольно простой хвостовой рекурсивный алгоритм, подобный показанному ниже:
import groovy.transform.CompileStatic
import groovy.transform.TailRecursive
@TailRecursive
@CompileStatic
<T> List<List<T>> combinations(final List<List<T>> xss, final List<List<T>> result = [[]]) {
return !xss ? result : combinations(xss.tail(), process(xss.head(), result))
}
@CompileStatic
<T> List<List<T>> process(final List<T> xs, final List<List<T>> result) {
return result.inject([]) { yss, ys -> yss + xs.collect { x -> ys + x } }
}
def values = [[1,2,3], [4,5],[6,7,8,9]]
def expected = [[1,4,6],[1,4,7],[1,4,8],[1,4,9],[1,5,6],[1,5,7],[1,5,8],[1,5,9],[2,4,6],[2,4,7],[2,4,8],[2,4,9],[2,5,6],[2,5,7],[2,5,8],[2,5,9],[3,4,6],[3,4,7],[3,4,8],[3,4,9],[3,5,6],[3,5,7],[3,5,8],[3,5,9]]
assert combinations(values) == expected