2016-12-22 8 views
3

Ich möchte eine Liste gleichmäßig auf eine bestimmte Anzahl von Unterlisten verteilen. Zum Beispiel habe ich eine Liste mit den Elementen 1 bis 10 und ich möchte 3 Listen. Diese sollten wie folgt aussehen:Gleichmäßige Verteilung von Listen in Unterlisten in Java

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

Wichtige: Was jede Liste enthält nicht relevant ist, das heißt SL1 könnte {1, 5, 7, 10}. Das Wichtigste ist, dass es 2 Listen mit Größe 3 und 1 Liste mit Größe 4 gibt.

Ich habe mehrere Dinge ausprobiert, einschließlich der Iterables.partition, aber das wird nicht helfen.

Das einzige, was ich bin gekommen, sich mit das funktioniert ist:

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; 
} 

Der übergebene bigList muss kein LinkedList sein, es kann jeder Iterable sein.

Ich hasse besonders die erste Schleife, wo ich die Unterlisten erstellen.

Danke!

Antwort

5

nur sie in einem Muster Round-Robin-Verteilung:

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; 
} 

Eine Probe Lauf mit diesem Code:

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()); 

Erzeugt

[[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] ]

Die Grundidee besteht darin, jeder Liste in der Ergebnismenge rundum ein einzelnes Element hinzuzufügen. Auf diese Weise wird garantiert, dass der Unterschied in der Anzahl der Elemente zwischen zwei Listen niemals 1 überschreitet.

Als Alternative könnten Sie die Guavas-Implementierung Iterables.partition verwenden, die einen etwas anderen Ansatz verfolgt.

+0

Große Liebe diese, danke! Irgendwie konnte ich die erste Schleife loswerden? Es war tatsächlich, was mich am meisten von meiner ursprünglichen Lösung stört. – user3083022

+0

@ user3083022 nicht wirklich. Du könntest ein wenig Magie verwenden, um es anders aussehen zu lassen, aber am Ende wirst du immer mit der Erstellung all dieser Listen-Instanzen enden. – Paul

+0

Über welche Art von Magie sprichst du?Auch wenn es sich um einen externen Einzeiler handelt, würde ich es nehmen – user3083022

2

Wenn Sie es hassen, Unterlisten zu erstellen, bedeutet das, dass Sie nach einer schnellen Lösung suchen. Wenn Sie das Original List haben und nicht das Original List ändern möchten, wählen Sie 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--; 
} 

Anmerkung: Ich schrieb dies ohne Prüfung - wenn es fehlschlägt, ich entschuldige mich, und hoffe, jemand wird bearbeiten zu arbeiten.

Noch einmal, das große Vorteil ist, dass es schnell böse sein sollte - alle Unterlisten sind nur Ansichten in die größere. Der Nachteil ist, dass wenn Sie die Liste ändern, alle Wetten aus sind.

+0

Dieser Code tut nicht was er soll. Nehmen wir an: 'input-list% numSubs = 3'. Ihr Code erzeugt 'numSubs - 1' Listen mit' subSize' Elementen und eine Liste mit 'subSize - 3' Elementen. – Paul

+0

Ich habe gerade den Code bearbeitet, um das Problem zu beheben. Wenn nun 'big.length() == 15 && numSubs == 4' ist, dann wird' subSize' nun auf 'big.length()/numSubs + 1 == 4' gesetzt, und Sie sollten jetzt Unterlisten bekommen geht 0-4, 4-8, 8-12, 12-15, was korrekt sein sollte. Was denken Sie? –

+0

(Das OP hat nicht vollständig spezifiziert, aber ich vermute Round-Robin ist erwünscht, wie Sie erwähnt haben, dh alle Unterlistenlängen sollten innerhalb von 1 voneinander liegen, wobei die ersten Unterlisten die größeren sind, falls nötig.) –

Verwandte Themen