Hello,
I worked out a more general solution to this problem. Per your requirement, you have an initial set of values that you would like to obtain combinations potentially using itertools.combinations
(as an example). You also stated that you would need to obtain results incrementally per “laggy generators” that don’t provide the values all at once.
To run this script, first create an instance by passing in the required combination length
integer as an argument. To obtain combination values, call the non_repeat_combos
method by passing in values in list format. As new value become available via the laggy generators
, append them to the existing list of values and recall the class method as needed. Note that the newly produced combinations per method call do not repeat. Only new combinations are produced as a function of the latest values appended to the existing list.
import itertools
#Use this class and method to pass in values incrementally
# as new values are being made available:
class IncrementalComboGenerator:
def __init__(self, combo_length):
self.combo_length = combo_length
self.latest_combos = []
self.all_combos = []
def non_repeat_combos(self, latest_list):
combo_diff = []
if not self.all_combos:
combo_diff = list(itertools.combinations(latest_list, self.combo_length))
for tup in combo_diff:
self.all_combos.append(tup)
elif not self.latest_combos:
self.latest_combos = list(itertools.combinations(latest_list, self.combo_length))
for combo_val in self.latest_combos:
if combo_val not in self.all_combos:
combo_diff.append(combo_val)
for tup in combo_diff:
self.all_combos.append(tup)
else:
self.latest_combos = list(itertools.combinations(latest_list, self.combo_length))
for combo_unit in self.latest_combos:
if combo_unit not in self.all_combos:
combo_diff.append(combo_unit)
for tup in combo_diff:
self.all_combos.append(tup)
return combo_diff
# Create instance - provide combination length
combos = IncrementalComboGenerator(3)
# Obtain combinations incrementally as you're obtaining new values
print(combos.non_repeat_combos([1,2,3,4])) # Original values
print(combos.non_repeat_combos([1,2,3,4,5])) # append new value 5
print(combos.non_repeat_combos([1,2,3,4,5,6])) # append new value 6
print(combos.non_repeat_combos([1,2,3,4,5,6,7])) # append new value 7
The following function processes values provided all at once.
def process_queue_combinations(queue, comb_length):
return list(itertools.combinations(queue, comb_length))
combination_length = 3
# Simulate available values from the generator
my_queue_1 = deque([1, 2, 3, 4, 5, 6, 7])
combinations_1 = process_queue_combinations(my_queue_1, combination_length)
for combo in combinations_1:
print(combo)
print(len(combinations_1))
If you compare the combinations produced by the function when values are passed all at once to the instance method where values are passed incrementally via multiple method calls, you will observe that they produce the same combinations.