2017-05-15 2 views
-1

Ich benutze itertools.combinations inconjunction mit itertools.cycle, um eine Reihe von Objekten zu erstellen, um eine andere Liste von Objekten zuzuweisen. Wenn die Listen nicht gleich lang oder eben teilbar sind, wird das erste Element in der Liste ungleichmäßig gewichtet.Distributed `iertools.combinations`

cycle_of_combinations = cycle(combinations(['A', 'B', 'C', 'D'], 2)) 
#(('A', 'B'), 
# ('A', 'C'), 
# ('A', 'D'), 
# ('B', 'C'), 
# ('B', 'D'), 
# ('C', 'D')) 

assigned_combinations = [] 
for _ in range(0, 9): 
    assigned_combinations.append(cycle_of_combinations.next()) 

# assigned_combinations = [ 
# ('A', 'B'), 
# ('A', 'C'), 
# ('A', 'D'), 
# ('B', 'C'), 
# ('B', 'D'), 
# ('C', 'D'), 
# ('A', 'B'), 
# ('A', 'C'), 
# ('A', 'D')] 

Im obigen Beispiel sind Kombinationen, die 'A' enthalten, überrepräsentiert. Gibt es einen schnellen Weg, um die Kombinationen besser zu verteilen?

Hier ist ein Beispiel eines Satzes, der gleichmäßiger verteilt, in diesem Satz würde ich jeden zweiten Punkt ausgewählt haben, bis 9 Elemente sind:

# assigned_combinations = [ 
# ('A', 'B'), 
# ('A', 'D'), 
# ('B', 'D'), 
# ('A', 'C'), 
# ('B', 'C'), 
# ('C', 'D'), 
# ('A', 'B'), 
# ('A', 'D'), 
# ('B', 'D')] 
+1

@ user2357112 wie zählen Sie? Ich bekomme "A" in 3 von 6 Kombinationen, mit "B", "C" und "D'" alle 3 von 6. –

+0

Warum haben Sie 'assigned_combinations' am 6. Element abgeschnitten? Das verbirgt verwirrend den Effekt, den du stoppen willst. – user2357112

+0

In ähnlicher Weise verbirgt Ihr Kommentar unter "cycle" die Tatsache, dass Sie tatsächlich einen Zyklus erstellt haben (und auch die Benennung der Variablen "cycle" verbirgt die importierte "cycle" -Funktion). – user2357112

Antwort

1

Sie könnten genug volle Zyklen erzeugen, die benötigt zur Deckung Listen Sie dann shuffle und trimmen Sie auf Größe. Die zurückgegebene Liste wird jedes Mal ein bisschen anders sein und Sie werden immer noch eine Überrepräsentation bekommen (dies ist unvermeidlich mit nicht übereinstimmenden Größen und random.shuffle kann es von Zeit zu Zeit deutlicher machen).

import math 
import itertools 
import random 

def get_combos(somelist, length, count): 
    combos = list(itertools.combinations(somelist, length)) 
    combos = combos * math.ceil(count/len(combos)) 
    random.shuffle(combos) 
    return combos[:count] 

for item in get_combos(['A', 'B', 'C', 'D'], 2, 9): 
    print(item)