2014-10-09 40 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