4

私は2つのリストを言うことができます:

def list1 = [a,b,c,d,e...]
def list2 = [1,2,3,4,5... ]

最終的なリストが次のようになるように、特定のパターンで混合してほしい。 [a,b,c,d,1,2,e,f,g,h,3,4,i,j,k,l,5,6...]

基本的にn、list1のすべての要素の後で、list2mから要素を取得します。

編集:1つのリストで要素が不足した場合、残りのリストの項目は単に最終リストに追加される必要があります。

EDIT2:両方のリストに要素としてオブジェクトを含めることができます。

この問題を解決するための最も効率的な方法を見つけたいと思います。

4

2 に答える 2

5

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']
于 2012-12-17T09:57:13.317 に答える
0

主な答えに基づいて残りの要素を保持する機能的なソリューションがあります。

List mix( Map<Integer,List> amounts ) {
    def maxItems = amounts.collect { k, v -> v.size() }.max()
    amounts.collect { k, v ->
        def padding = maxItems - v.size()
        it.addAll((1..padding).collect { null })
        v.collate( k )
    }.transpose().flatten().grep { it }
}

一度に1つのアイテムを取得する3つのリストを混合するために、簡略化されたバージョンでテストしました。アイデアは、nullオブジェクトでパディングを追加して、すべてを同じ長さにすることです。

于 2013-05-14T22:42:31.837 に答える