2014-10-09 81 views
5

有沒有方法或一些聰明的方法,很容易閱讀,使Groovy中的元素成爲combination?我知道Iterable#combinationsGroovyCollections#combinations,但它使得部分排列重複據我瞭解到目前爲止。看例子。Groovy中的真實組合

// Groovy combinations result 
def e = ['a', 'b', 'c'] 
def result = [e, e].combinations() 
assert [['a', 'a'], ['b', 'a'], ['c', 'a'], ['a', 'b'], ['b', 'b'], ['c', 'b'], ['a','c'], ['b', 'c'], ['c', 'c']] == result 

// What I'm looking for 
def e = ['a', 'b', 'c'] 
def result = ??? 
assert [['a', 'b'], ['a', 'c'], ['b', 'c']] == result 

隨意張貼替代解決方案。我仍然在尋找更好的可讀性(它在腳本中用於非開發人員)和性能(沒有不必要的迭代)。

回答

9

我對可讀性不是很確定,但是這應該可以做到。

def e = ['a', 'b', 'c'] 
def result = [e, e].combinations().findAll { a, b -> 
    a < b 
} 

assert [['a', 'b'], ['a', 'c'], ['b', 'c']] == result 

請注意,如果一個元素在列表中出現兩次,它的組合也會出現兩次。如果它們不需要,最後在末尾添加'.unique()'

+0

謝謝。就一件事。你甚至不必測試!= b cos這個條件包含在 2014-10-09 08:57:24

+0

這是真的,編輯它。謝謝。 – Kaffeleif 2014-10-09 09:04:34

7

下面是一個更通用的方法,允許您指定nCr組合的「r」值。它通過在集合中存儲排列來完成此操作,集合提供唯一性:

// returns combinations of the input list of the provided size, r 
List combinationsOf(List list, int r) { 
    assert (0..<list.size()).contains(r) // validate input 
    def combs = [] as Set 
    list.eachPermutation { 
     combs << it.subList(0, r).sort { a, b -> a <=> b } 
    } 
    combs as List 
} 

// the test scenario... 
def e = ['a', 'b', 'c'] 
def result = combinationsOf(e, 2) 
assert [['a', 'b'], ['a', 'c'], ['b', 'c']] == result