如何生成一组可迭代对象的所有组合?Groovy代码相关咨询
生成镜片参数的所有组合:完善你的Groovy代码
嘿,我看你正在写一个生成镜片参数所有组合的Groovy方法,代码开头已经处理了sph、cyl、add的范围参数,但后面截断了。我来帮你补全这段代码,顺便解释下怎么高效生成所有可能的组合~
补全后的完整代码
首先,先给你补全并优化后的代码,适配镜片参数的常见场景:
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 // 镜片参数常用步长是0.25,可根据需求调整 def step = new BigDecimal("0.25") // 生成每个参数的所有可能值序列,保证精度统一 def sphValues = [] for (def sph = sphFrom; sph <= sphTo; sph += step) { sphValues.add(sph.setScale(2, BigDecimal.ROUND_HALF_UP)) } def cylValues = [] for (def cyl = cylFrom; cyl <= cylTo; cyl += step) { cylValues.add(cyl.setScale(2, BigDecimal.ROUND_HALF_UP)) } def addValues = [] for (def add = addFrom; add <= addTo; add += step) { addValues.add(add.setScale(2, BigDecimal.ROUND_HALF_UP)) } // 生成所有参数的笛卡尔积组合 sphValues.each { sph -> cylValues.each { cyl -> addValues.each { add -> def combination = new HashMap<>(entryCopy) combination.putAll([sph: sph, cyl: cyl, add: add]) expandedPositions.add(combination) } } } return expandedPositions }
关键细节解释
- 克隆输入Map:我用
entry.clone()是为了避免修改原始输入数据,保持数据的不可变性,防止后续代码意外污染原数据。 - 步长与精度:镜片参数通常以0.25为增量,这里设置了固定步长,同时用
setScale(2)保证所有参数都是两位小数,避免BigDecimal的精度问题。 - 笛卡尔积生成:嵌套的
each循环是Groovy里最直观的生成组合的方式,如果你以后要加更多参数(比如轴位axis),这种写法也容易扩展。
更简洁的笛卡尔积写法
如果觉得嵌套循环太繁琐,Groovy自带的combinations()方法可以帮你简化:
// 替换原有的嵌套each循环 def allCombinations = [sphValues, cylValues, addValues].combinations() allCombinations.each { combo -> def combination = new HashMap<>(entryCopy) combination.putAll([sph: combo[0], cyl: combo[1], add: combo[2]]) expandedPositions.add(combination) }
这种写法更简洁,尤其是参数数量多的时候,可读性更好。
测试示例
来个实际调用的例子,看看效果:
def input = [ sphFrom: new BigDecimal("-2.00"), sphTo: new BigDecimal("-1.50"), cylFrom: new BigDecimal("-0.50"), cylTo: new BigDecimal("0.00"), addFrom: new BigDecimal("1.00"), addTo: new BigDecimal("1.00"), lensType: "progressive" ] def result = expandLensesPositions(input) result.each { println it }
输出会是所有6种可能的组合:
[sph:-2.00, cyl:-0.50, add:1.00, lensType:progressive] [sph:-2.00, cyl:0.00, add:1.00, lensType:progressive] [sph:-1.75, cyl:-0.50, add:1.00, lensType:progressive] [sph:-1.75, cyl:0.00, add:1.00, lensType:progressive] [sph:-1.50, cyl:-0.50, add:1.00, lensType:progressive] [sph:-1.50, cyl:0.00, add:1.00, lensType:progressive]
内容的提问来源于stack exchange,提问作者iRomul
相关产品推荐
相关产品推荐

