我需要创建一组可迭代对象的所有组合。 我在Groovy上有一些用于生成组合的代码:
private static List<Map> expandLensesPositions(Map entry) {
def expandedPositions = []
def entryCopy = entry.clone() as Map
def sphFrom = entryCopy.remove("sphFrom") as BigDecimal
def sphTo = entryCopy.remove("sphTo") as BigDecimal
def cylFrom = entryCopy.remove("cylFrom") as BigDecimal
def cylTo = entryCopy.remove("cylTo") as BigDecimal
def addFrom = entryCopy.remove("addFrom") as BigDecimal
def addTo = entryCopy.remove("addTo") as BigDecimal
def diameter = entryCopy.remove("diameterFrom")
for (def sph in generateSeries(sphFrom, sphTo)) {
for (def cyl in generateSeries(cylFrom, cylTo)) {
for (def add in generateSeries(addFrom, addTo)) {
def expandedEntryProps = [dioptre:sph, diameter:diameter, cylinderDioptre:cyl, addidation:add]
expandedPositions << entryCopy + expandedEntryProps
}
}
}
return expandedPositions
}
在此代码generateSeries(from, to)
中返回Iterable<BigDecimal>
个对象。在此实现中,结果存储在ArrayList expandedPositions
中,但是这种方法对于大量结果元素是不可接受的。有没有办法为所有可迭代对象创建包装器并迭代所有组合?
答案 0 :(得分:1)
在Groovy中,您可以使用GroovyCollections.combinations(Iterable collection)
函数创建所有组合的列表,例如
[[0,1], [2,3], [4,5]].combinations()
创建以下组合列表:
[[0, 2, 4], [1, 2, 4], [0, 3, 4], [1, 3, 4], [0, 2, 5], [1, 2, 5], [0, 3, 5], [1, 3, 5]]
请考虑以下创建地图条目列表的示例:
def sph = [1,2,3,4,5]
def cyl = [6,7,8,9,10]
def add = [11,12,13,14,15]
def diameter = 0.0
def result = [sph, cyl, add].combinations().collect { row ->
[dioptre: row[0], diameter: diameter, cylinderDioptre: row[1], addidation: row[2]]
}
result.each {
println it
}
它创建的输出遵循(125种组合):
[dioptre:1, diameter:0.0, cylinderDioptre:6, addidation:11]
[dioptre:2, diameter:0.0, cylinderDioptre:6, addidation:11]
[dioptre:3, diameter:0.0, cylinderDioptre:6, addidation:11]
[dioptre:4, diameter:0.0, cylinderDioptre:6, addidation:11]
[dioptre:5, diameter:0.0, cylinderDioptre:6, addidation:11]
[dioptre:1, diameter:0.0, cylinderDioptre:7, addidation:11]
[dioptre:2, diameter:0.0, cylinderDioptre:7, addidation:11]
[dioptre:3, diameter:0.0, cylinderDioptre:7, addidation:11]
[dioptre:4, diameter:0.0, cylinderDioptre:7, addidation:11]
[dioptre:5, diameter:0.0, cylinderDioptre:7, addidation:11]
[dioptre:1, diameter:0.0, cylinderDioptre:8, addidation:11]
[dioptre:2, diameter:0.0, cylinderDioptre:8, addidation:11]
[dioptre:3, diameter:0.0, cylinderDioptre:8, addidation:11]
[dioptre:4, diameter:0.0, cylinderDioptre:8, addidation:11]
[dioptre:5, diameter:0.0, cylinderDioptre:8, addidation:11]
[dioptre:1, diameter:0.0, cylinderDioptre:9, addidation:11]
[dioptre:2, diameter:0.0, cylinderDioptre:9, addidation:11]
[dioptre:3, diameter:0.0, cylinderDioptre:9, addidation:11]
[dioptre:4, diameter:0.0, cylinderDioptre:9, addidation:11]
[dioptre:5, diameter:0.0, cylinderDioptre:9, addidation:11]
[dioptre:1, diameter:0.0, cylinderDioptre:10, addidation:11]
[dioptre:2, diameter:0.0, cylinderDioptre:10, addidation:11]
[dioptre:3, diameter:0.0, cylinderDioptre:10, addidation:11]
[dioptre:4, diameter:0.0, cylinderDioptre:10, addidation:11]
[dioptre:5, diameter:0.0, cylinderDioptre:10, addidation:11]
[dioptre:1, diameter:0.0, cylinderDioptre:6, addidation:12]
[dioptre:2, diameter:0.0, cylinderDioptre:6, addidation:12]
[dioptre:3, diameter:0.0, cylinderDioptre:6, addidation:12]
[dioptre:4, diameter:0.0, cylinderDioptre:6, addidation:12]
[dioptre:5, diameter:0.0, cylinderDioptre:6, addidation:12]
[dioptre:1, diameter:0.0, cylinderDioptre:7, addidation:12]
[dioptre:2, diameter:0.0, cylinderDioptre:7, addidation:12]
[dioptre:3, diameter:0.0, cylinderDioptre:7, addidation:12]
[dioptre:4, diameter:0.0, cylinderDioptre:7, addidation:12]
[dioptre:5, diameter:0.0, cylinderDioptre:7, addidation:12]
[dioptre:1, diameter:0.0, cylinderDioptre:8, addidation:12]
[dioptre:2, diameter:0.0, cylinderDioptre:8, addidation:12]
[dioptre:3, diameter:0.0, cylinderDioptre:8, addidation:12]
[dioptre:4, diameter:0.0, cylinderDioptre:8, addidation:12]
[dioptre:5, diameter:0.0, cylinderDioptre:8, addidation:12]
[dioptre:1, diameter:0.0, cylinderDioptre:9, addidation:12]
[dioptre:2, diameter:0.0, cylinderDioptre:9, addidation:12]
[dioptre:3, diameter:0.0, cylinderDioptre:9, addidation:12]
[dioptre:4, diameter:0.0, cylinderDioptre:9, addidation:12]
[dioptre:5, diameter:0.0, cylinderDioptre:9, addidation:12]
[dioptre:1, diameter:0.0, cylinderDioptre:10, addidation:12]
[dioptre:2, diameter:0.0, cylinderDioptre:10, addidation:12]
[dioptre:3, diameter:0.0, cylinderDioptre:10, addidation:12]
[dioptre:4, diameter:0.0, cylinderDioptre:10, addidation:12]
[dioptre:5, diameter:0.0, cylinderDioptre:10, addidation:12]
[dioptre:1, diameter:0.0, cylinderDioptre:6, addidation:13]
[dioptre:2, diameter:0.0, cylinderDioptre:6, addidation:13]
[dioptre:3, diameter:0.0, cylinderDioptre:6, addidation:13]
[dioptre:4, diameter:0.0, cylinderDioptre:6, addidation:13]
[dioptre:5, diameter:0.0, cylinderDioptre:6, addidation:13]
[dioptre:1, diameter:0.0, cylinderDioptre:7, addidation:13]
[dioptre:2, diameter:0.0, cylinderDioptre:7, addidation:13]
[dioptre:3, diameter:0.0, cylinderDioptre:7, addidation:13]
[dioptre:4, diameter:0.0, cylinderDioptre:7, addidation:13]
[dioptre:5, diameter:0.0, cylinderDioptre:7, addidation:13]
[dioptre:1, diameter:0.0, cylinderDioptre:8, addidation:13]
[dioptre:2, diameter:0.0, cylinderDioptre:8, addidation:13]
[dioptre:3, diameter:0.0, cylinderDioptre:8, addidation:13]
[dioptre:4, diameter:0.0, cylinderDioptre:8, addidation:13]
[dioptre:5, diameter:0.0, cylinderDioptre:8, addidation:13]
[dioptre:1, diameter:0.0, cylinderDioptre:9, addidation:13]
[dioptre:2, diameter:0.0, cylinderDioptre:9, addidation:13]
[dioptre:3, diameter:0.0, cylinderDioptre:9, addidation:13]
[dioptre:4, diameter:0.0, cylinderDioptre:9, addidation:13]
[dioptre:5, diameter:0.0, cylinderDioptre:9, addidation:13]
[dioptre:1, diameter:0.0, cylinderDioptre:10, addidation:13]
[dioptre:2, diameter:0.0, cylinderDioptre:10, addidation:13]
[dioptre:3, diameter:0.0, cylinderDioptre:10, addidation:13]
[dioptre:4, diameter:0.0, cylinderDioptre:10, addidation:13]
[dioptre:5, diameter:0.0, cylinderDioptre:10, addidation:13]
[dioptre:1, diameter:0.0, cylinderDioptre:6, addidation:14]
[dioptre:2, diameter:0.0, cylinderDioptre:6, addidation:14]
[dioptre:3, diameter:0.0, cylinderDioptre:6, addidation:14]
[dioptre:4, diameter:0.0, cylinderDioptre:6, addidation:14]
[dioptre:5, diameter:0.0, cylinderDioptre:6, addidation:14]
[dioptre:1, diameter:0.0, cylinderDioptre:7, addidation:14]
[dioptre:2, diameter:0.0, cylinderDioptre:7, addidation:14]
[dioptre:3, diameter:0.0, cylinderDioptre:7, addidation:14]
[dioptre:4, diameter:0.0, cylinderDioptre:7, addidation:14]
[dioptre:5, diameter:0.0, cylinderDioptre:7, addidation:14]
[dioptre:1, diameter:0.0, cylinderDioptre:8, addidation:14]
[dioptre:2, diameter:0.0, cylinderDioptre:8, addidation:14]
[dioptre:3, diameter:0.0, cylinderDioptre:8, addidation:14]
[dioptre:4, diameter:0.0, cylinderDioptre:8, addidation:14]
[dioptre:5, diameter:0.0, cylinderDioptre:8, addidation:14]
[dioptre:1, diameter:0.0, cylinderDioptre:9, addidation:14]
[dioptre:2, diameter:0.0, cylinderDioptre:9, addidation:14]
[dioptre:3, diameter:0.0, cylinderDioptre:9, addidation:14]
[dioptre:4, diameter:0.0, cylinderDioptre:9, addidation:14]
[dioptre:5, diameter:0.0, cylinderDioptre:9, addidation:14]
[dioptre:1, diameter:0.0, cylinderDioptre:10, addidation:14]
[dioptre:2, diameter:0.0, cylinderDioptre:10, addidation:14]
[dioptre:3, diameter:0.0, cylinderDioptre:10, addidation:14]
[dioptre:4, diameter:0.0, cylinderDioptre:10, addidation:14]
[dioptre:5, diameter:0.0, cylinderDioptre:10, addidation:14]
[dioptre:1, diameter:0.0, cylinderDioptre:6, addidation:15]
[dioptre:2, diameter:0.0, cylinderDioptre:6, addidation:15]
[dioptre:3, diameter:0.0, cylinderDioptre:6, addidation:15]
[dioptre:4, diameter:0.0, cylinderDioptre:6, addidation:15]
[dioptre:5, diameter:0.0, cylinderDioptre:6, addidation:15]
[dioptre:1, diameter:0.0, cylinderDioptre:7, addidation:15]
[dioptre:2, diameter:0.0, cylinderDioptre:7, addidation:15]
[dioptre:3, diameter:0.0, cylinderDioptre:7, addidation:15]
[dioptre:4, diameter:0.0, cylinderDioptre:7, addidation:15]
[dioptre:5, diameter:0.0, cylinderDioptre:7, addidation:15]
[dioptre:1, diameter:0.0, cylinderDioptre:8, addidation:15]
[dioptre:2, diameter:0.0, cylinderDioptre:8, addidation:15]
[dioptre:3, diameter:0.0, cylinderDioptre:8, addidation:15]
[dioptre:4, diameter:0.0, cylinderDioptre:8, addidation:15]
[dioptre:5, diameter:0.0, cylinderDioptre:8, addidation:15]
[dioptre:1, diameter:0.0, cylinderDioptre:9, addidation:15]
[dioptre:2, diameter:0.0, cylinderDioptre:9, addidation:15]
[dioptre:3, diameter:0.0, cylinderDioptre:9, addidation:15]
[dioptre:4, diameter:0.0, cylinderDioptre:9, addidation:15]
[dioptre:5, diameter:0.0, cylinderDioptre:9, addidation:15]
[dioptre:1, diameter:0.0, cylinderDioptre:10, addidation:15]
[dioptre:2, diameter:0.0, cylinderDioptre:10, addidation:15]
[dioptre:3, diameter:0.0, cylinderDioptre:10, addidation:15]
[dioptre:4, diameter:0.0, cylinderDioptre:10, addidation:15]
[dioptre:5, diameter:0.0, cylinderDioptre:10, addidation:15]
我猜这个最终列表并不完全符合您的预期,因为在您的示例中,您将元素推送到最终列表
expandedPositions << entryCopy + expandedEntryProps
但做这样的事情:
def result = [sph, cyl, add].combinations().collect { row ->
entryCopy + [dioptre: row[0], diameter: diameter, cylinderDioptre: row[1], addidation: row[2]]
}
应该这样做。
正如您在下面的评论中所提到的,GroovyCollections.combinations(iterable)
会创建一个列表并将所有组合存储在其中。如果您希望以更懒惰的方式创建组合,可以考虑使用自定义Iterator
来计算特定迭代步骤的组合。请考虑以下示例:
final class LazyCombinationsIterator<T> implements Iterator<List<T>> {
final AtomicInteger idx = new AtomicInteger(0)
final List<List<T>> lists = []
final int size
final List<Integer> listCycle
LazyCombinationsIterator(List<T>... lists) {
this.lists.addAll(lists)
this.size = (int) lists.inject(1) { acc, list -> acc * list.size() }
this.listCycle = [1] + (lists.inject([]) { List<Integer> acc, list ->
acc << (acc.isEmpty() ? list.size() : acc.last() * list.size())
} as List)
}
@Override
boolean hasNext() {
return idx.get() < size
}
@Override
List<T> next() {
final int i = idx.getAndIncrement()
final int to = lists.size()
return (0..<(to)).collect {
final List<T> list = lists.get(it)
final int listIdx = (int) (i / listCycle.get(it))
return list.get(listIdx % list.size())
}
}
}
此自定义迭代器至少需要两个类型为T
的列表,并在迭代时生成计算。它创建与GroovyCollections.combinations(iterable)
函数相同的输出,但它会懒惰地执行。
new LazyCombinationsIterator<>([1, 2], [3, 4, 5], [6, 9]).each {
println it
}
它创建以下输出:
[1, 3, 6]
[2, 3, 6]
[1, 4, 6]
[2, 4, 6]
[1, 5, 6]
[2, 5, 6]
[1, 3, 9]
[2, 3, 9]
[1, 4, 9]
[2, 4, 9]
[1, 5, 9]
[2, 5, 9]
new LazyCombinationsIterator<>(['a', 'b'], ['c'], ['d', 'e']).each {
println it
}
它创建以下输出:
[a, c, d]
[b, c, d]
[a, c, e]
[b, c, e]