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 1s 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]]





Going to look into this one a bit more, the way cycly works intrigues me. Thanks.
– Mathieu
Jun 29 at 10:58





@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.

Comments

Popular posts from this blog

paramiko-expect timeout is happening after executing the command

how to run turtle graphics in Colaboratory

Export result set on Dbeaver to CSV