Groovyでこれを行う1つの方法は次のとおりです。
だから私は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 ]
(ここで見栄えがするようにフォーマットされています)
ご覧のとおり、最初に番号が不足し、不足するとリストが終了します。これは、1つのリストの要素がなくなると転置が停止するためです。
編集:
イテレータを使用して別の方法で解決しました(怠惰で、他の方法で必要とされるよりも多くのメモリを消費しません):
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']