这是在 Groovy 中执行此操作的一种方法:
所以我有一个方法mix
,它采用整数键(所需元素的数量)和列表作为值的映射:
List mix( Map<Integer,List> amounts ) {
amounts.collect { k, v ->
v.collate( k )
}.transpose().flatten()
}
然后,给定:
// The letters a to z
def list1 = 'a'..'z'
// The numbers 1 to 10
def list2 = 1..10
// Call, and ask for 4 of list1 followed by 2 of list2
mix( [ 4:list1, 2:list2 ] )
返回:
[ 'a', 'b', 'c', 'd', 1, 2,
'e', 'f', 'g', 'h', 3, 4,
'i', 'j', 'k', 'l', 5, 6,
'm', 'n', 'o', 'p', 7, 8,
'q', 'r', 's', 't', 9, 10 ]
(格式化为在这里更好看)
如您所见,它首先用完数字,当它用完时,列表结束。这是因为当一个列表用完元素时转置停止。
编辑:
用迭代器解决了另一种方法(所以它很懒,不会占用比其他需要更多的内存):
class MixingIterator<T> implements Iterator<T> {
private int idx = 0
private List<Iterator> iter
private List<Integer> amts
MixingIterator( List<List> lists, List<Integer> amounts ) {
iter = lists*.iterator()
int i = 0
amts = amounts.collectMany { [ i++ ] * it }
// OR FOR GROOVY 1.7.8
// amts = amounts.collect { [ i++ ] * it }.flatten()
}
private void moveIdx() {
idx = ++idx % amts.size()
}
@Override boolean hasNext() {
iter*.hasNext().any()
}
@Override T next() {
if( !hasNext() ) { throw new NoSuchElementException() }
while( !iter[ amts[ idx ] ].hasNext() ) { moveIdx() }
T ret = iter[ amts[ idx ] ].next()
moveIdx()
ret
}
@Override void remove() {
throw new UnsupportedOperationException()
}
}
您通过以下方式调用它:
def list1 = 'a'..'z'
def list2 = 1..10
def ret = new MixingIterator( [ list1, list2 ], [ 4, 2 ] ).collect()
// OR FOR GROOVY 1.7.8
// def ret = new MixingIterator( [ list1, list2 ], [ 4, 2 ] ).collect { it }
然后 ret 将等于:
['a', 'b', 'c', 'd', 1, 2,
'e', 'f', 'g', 'h', 3, 4,
'i', 'j', 'k', 'l', 5, 6,
'm', 'n', 'o', 'p', 7, 8,
'q', 'r', 's', 't', 9, 10,
'u', 'v', 'w', 'x', 'y', 'z']