Keeping track of which subset is computed to avoid mixing the results
Keeping track of which subset is computed to avoid mixing the results
tricky name and unclear name...
My issue is the following:
import itertools
t0 = 0
tf = 1000000
# inputs_to_compute = list-like of size 2 to 6 of objects
results = [ for i in range(len(inputs_to_compute))]
for subset in itertools.combinations(inputs_to_compute, 2):
r1, r2 = compute(subset[0], subset[1], t0, tf)
results[inputs_to_compute.index(subset[0])] += list(r1)
results[inputs_to_compute.index(subset[1])] += list(r2)
This code is creating as many results lists as there is an input. Each input is actually associated to a list. Then the computation is performed 2 by 2 (on each subset) and the result is added to the corresponding list.
It works well as long as there is no repetition in the inputs because the method index
returns the first occurrence of the element. How could I implement this differently (and efficiently, performance is one of the main issue I have) in a way that manage duplicates?
index
Dummy example:
import itertools
def compute(x, y):
return (x + y, x - y)
inputs_to_compute = [1, 1, 3]
results = [ for i in range(len(inputs_to_compute))]
for subset in itertools.combinations(inputs_to_compute, 2):
r1, r2 = compute(subset[0], subset[1])
results[inputs_to_compute.index(subset[0])].append(r1)
results[inputs_to_compute.index(subset[1])].append(r2)
Output:
[[2, 0, 4, 4], , [-2, -2]]
Expected output:
# Iteration (1, 1): r1 = 2, r2 = 0
results = [[2], [0], ]
# Iteration (1, 3): r1 = 4, r2 = -2
results = [[2, 4], [0], [-2]]
# Iteration (1, 3): r1 = 4, r2 = -2
results = [[2, 4], [0, 4], [-2, -2]]
3 Answers
3
for subset_with_indices in itertools.combinations(enumerate(inputs_to_compute), 2):
i1,x1 = subset_with_indices[0]
i2,x2 = subset_with_indices[1]
r1, r2 = compute(x1, x2)
results[i1].append(r1)
results[i2].append(r2)
If I understood this correctly, then you want to cycle between the repeated 1
s every time they are returned as part of subset
.
1
subset
One way to do this is to create a dictionary with the item as key and its indices stored in a list. Once we have this dict we can apply itertools.cycle
to the list and then use next()
to cycle between an items's indices:
itertools.cycle
next()
import itertools
def compute(x, y):
return (x + y, x - y)
inputs_to_compute = [1, 1, 3]
indices = {}
for ind, item in enumerate(inputs_to_compute):
indices.setdefault(item, ).append(ind)
for k, v in indices.items():
indices[k] = itertools.cycle(v)
results = [ for i in range(len(inputs_to_compute))]
for subset in itertools.combinations(inputs_to_compute, 2):
r1, r2 = compute(subset[0], subset[1])
results[next(indices[subset[0]])].append(r1)
results[next(indices[subset[1]])].append(r2)
Output:
>>> %run so.py
>>> results
[[2, 4], [0, 4], [-2, -2]]
@Mathieu Note that the selected answer and this do different things, they just happen to have same output for the above input. You might wanna compare with something like
inputs_to_compute = [1, 1, 1, 3]
for example.– Ashwini Chaudhary
Jun 29 at 11:00
inputs_to_compute = [1, 1, 1, 3]
Your answer is slightly more complicated. I've figure out something simple and working on the indices based on the accepted answer.
– Mathieu
Jun 29 at 11:06
And I will compare :)
– Mathieu
Jun 29 at 11:07
in the docs you have a recipe for combinations that uses permutations[1]. you just modify it to return indices
import itertools
def compute(x, y):
return (x + y, x - y)
def combinations(iterable, r):
pool = tuple(iterable)
n = len(pool)
for indices in itertools.permutations(range(n), r):
if sorted(indices) == list(indices):
yield tuple(indices)
inputs_to_compute = [1, 1, 3]
results = [ for i in range(len(inputs_to_compute))]
for i1, i2 in combinations(inputs_to_compute, 2):
r1, r2 = compute(inputs_to_compute[i1], inputs_to_compute[i2])
results[i1].append(r1)
results[i2].append(r2)
print(results)
[1] https://docs.python.org/3/library/itertools.html#itertools.combinations
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Going to look into this one a bit more, the way cycly works intrigues me. Thanks.
– Mathieu
Jun 29 at 10:58