2016-12-22 16 views
3

リストを指定した数のサブリストに均等に分配したい。 たとえば、要素1〜10のリストがあり、3つのリストが必要です。リストをJavaのサブリストに均等に配布する

SL1 -> {1, 2, 3, 4} 
SL2 -> {5, 6, 7} 
SL3 -> {8, 9, 10} 

重要:これらはどのように見えるかを各リストに含まれていることは関係ありません、すなわちSL1は{1、5、7、10}を持つことができます。最も重要なことは、サイズが3のリストとサイズが4のリストが2つあることです。

私はIterables.partitionを含むいくつかのことを試しましたが、それは役に立たないでしょう。

私はそれが作品を作ってみただけの事はある:

public Iterable<List<Integer>> distributeEvenlyQueryListIntoLists(final LinkedList<Integer> bigList, final Integer numberOfSublists) { 
    List<List<Integer>> result = new ArrayList<>(); 

    // Creates as many lists as needed 
    for (int i = 0; i < numberOfSublists; i++) { 
     result.add(new ArrayList<>()); 
    } 

    while (bigList.iterator().hasNext()) { 
     for (int i = 0; i < numberOfSublists; i++) { 
      if (!bigList.iterator().hasNext()) { 
       break; 
      } 
      result.get(i).add(bigList.poll()); 
     } 
    } 
    return result; 
} 

渡さbigListは、それがどのIterableすることができ、LinkedListである必要はありません。

特に私がサブリストを作成する最初のループは嫌いです。

ありがとうございます!

答えて

5

ちょうどラウンドロビンパターンで配布:

public <T> List<List<T>> partition(Iterable<T> iterable, int partitions){ 
    List<List<T>> result = new ArrayList<>(partitions); 
    for(int i = 0; i < partitions; i++) 
     result.add(new ArrayList<>()); 

    Iterator<T> iterator = iterable.iterator() 
    for(int i = 0; iterator.hasNext(); i++) 
     result.get(i % partitions).add(iterator.next()); 

    return result; 
} 

このコードのサンプルのラン:

List<String> l = Stream.iterate(0, i->i + 1).limit(25).map(i->Integer.toString(i)).collect(Collectors.toList()); 
System.out.println(partition(l, 4).toString()); 

が生産

[0、4、8、 12]、[16、20、24]、[1,5,9,13,17,21]、[2,6,10,14,18,22]、[3,7,11,15,19,23] ]

基本的な考え方は、結果セットの各リストに1つの要素を丸で追加することです。これにより、2つのリスト間の要素数の差が決して1を超えないことが保証されます。

代わりにguavasの実装をIterables.partitionとすることができます。

+0

大変この1つ、ありがとう!私は最初のループを取り除くことができる任意の方法ですか?実際に私の元の解決策から私を悩ましていたものでした。 – user3083022

+0

@ user3083022本当にありません。あなたはそれを違ったものにするために少しの魔法を使うことができますが、結局、それらのすべてのリストインスタンスを作成することに終わります。 – Paul

+0

あなたはどんな魔法について話していますか?たとえそれが外部の1つのライナーであっても、私はそれを取るでしょう – user3083022

2

サブリストの作成が嫌な場合は、高速ソリューションを探していることを意味します。 元のListがあり、オリジナルを変更しない場合は、Listと入力してください。List.subList()としてください。

int subSize = bigList.length()/numSubs; 
int numBigSubs = 0; // # of subs that need to be one bigger 
if (bigList.length() % numSubs > 0) { 
    subSize++; 
    numBigSubs = bigList.length() % numSubs; 
} 
int from = 0; 
int to = subSize; 
List<List<Integer>> subList = new ArrayList<List<Integer>>(numSubs); 
for (int i = 0; i < numSubs; i++) { 
    List<Integer> newSub = bigList.subList(from, to); 
    subList.add (newSub); 
    from = to; 
    to += subSize; 
    if (i >= numBigSubs && numBigSubs > 0) to--; 
} 

注:私はテストせずにこれを書いている - それが失敗した場合、私は謝罪し、誰かが動作するように編集されます願っています。

また、この大きな大きな欠点は、邪悪な速さでなければならないということです。すべてのサブリストは、大きなものへの単純なビューです。欠点は、リストを変更すると、すべてのベットがオフになっていることです。

+0

このコードは、それが想定していることをしません。 'input-list%numSubs = 3'とします。あなたのコードは、 'subSize'要素を持つ' numSubs - 1'リストと 'subSize - 3'要素を持つリストを生成します。 – Paul

+0

これを処理するコードを編集していただけなので、あなたの懸念に対処するかもしれません。さて、 'big.length()== 15 && numSubs == 4'なら、' subSize'は 'big.length()/ numSubs + 1 == 4'に設定されます。 0-4、4-8、8-12、12-15になりますが、これは正しいはずです。どう思いますか? –

+0

(OPは完全には指定されていませんが、あなたが言及したようにラウンドロビンが必要であると推測しています。つまり、すべてのサブリストの長さは互いに1以内でなければなりません)。 –

関連する問題