既然你要處理整個列表,一個很好的選擇是利用常規收集的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