既然你要处理整个列表,一个很好的选择是利用常规收集的inject方法(添加println
显示步骤):
def values = [[72, 83], [72, 127], [83, 127], [110, 119]]
def result = values.inject([], { res, value ->
println "res = $res | value = $value"
def found = res.find {
if (it.intersect(value)) {
it.addAll(value - it)
true
}
}
if (!found) {
res << value
}
res
})
println result
assert [[72, 83, 127], [110, 119]] == result
这样:
res = [] | value = [72, 83]
res = [[72, 83]] | value = [72, 127]
res = [[72, 83, 127]] | value = [83, 127]
res = [[72, 83, 127]] | value = [110, 119]
[[72, 83, 127], [110, 119]]
编辑:上述方案在某些情况下效果不佳,即:
def values = [[72, 83], [72, 127], [83, 127], [110, 119], [47, 56], [56, 72]]
个
产量
[[72, 83, 127, 56], [110, 119], [47, 56]]
而如果列表进行排序它的产量(我认为这是正确的解决方案)
[[47, 56, 72, 83, 127], [110, 119]]
EDIT(2):一个更好的解决方案,解决了以往问题(即列表共享元素与几个结果列表):
def values = [[72, 83], [72, 127], [83, 127], [110, 119], [120, 121], [121, 127]]
def result = values.inject([], { res, value ->
println "res = $res | value = $value"
def found = res.findAll { it.intersect(value) }
println " -> found = $found"
if (!found) {
res << value
} else {
res.removeAll(found)
def merged = found.collect({ it + value as Set }).flatten() as Set
println " -> merged = $merged"
res << merged
}
println " => res = $res"
res
})
我完全困惑于你想如何决定输入中的一个元素应该进入哪个输出列表。 – 2015-04-04 11:19:43
好吧,子列表0包含72和83.子列表1包含72和127.由于两者都包含72,所以我们合并它们。子列表2包含83和127.由于子列表1还包含83(或第二个包含128),所以我们也合并了子列表1和3. – Bob 2015-04-04 11:21:45
所以......你是说你想合并列表如果交叉点他们之间是不是空的? – 2015-04-04 11:22:42