I'm trying to create a list of tuples in python with the combinations of first element of list with the rest elements of the list but without repeat the first element of the tuple in final result of combinations
I use this:
lst = [(2, 'ok'), (3, 'ok'), (3, 'fail'), (3, 'error'), (4, 'ok'), (4, 'fail'), (4, 'error')]
data = [[lst[0]] list(i) for i in itertools.combinations(lst[1:], 2)]
for i in data:
print(i)
and get this:
[(2, 'ok'), (3, 'ok'), (3, 'ok')]
[(2, 'ok'), (3, 'ok'), (3, 'fail')]
[(2, 'ok'), (3, 'ok'), (3, 'error')]
[(2, 'ok'), (3, 'ok'), (4, 'ok')]
[(2, 'ok'), (3, 'ok'), (4, 'fail')]
[(2, 'ok'), (3, 'ok'), (4, 'error')]
[(2, 'ok'), (3, 'fail'), (3, 'fail')]
[(2, 'ok'), (3, 'fail'), (3, 'error')]
[(2, 'ok'), (3, 'fail'), (4, 'ok')]
[(2, 'ok'), (3, 'fail'), (4, 'fail')]
[(2, 'ok'), (3, 'fail'), (4, 'error')]
[(2, 'ok'), (3, 'error'), (3, 'error')]
[(2, 'ok'), (3, 'error'), (4, 'ok')]
[(2, 'ok'), (3, 'error'), (4, 'fail')]
[(2, 'ok'), (3, 'error'), (4, 'error')]
[(2, 'ok'), (4, 'ok'), (4, 'ok')]
[(2, 'ok'), (4, 'ok'), (4, 'fail')]
[(2, 'ok'), (4, 'ok'), (4, 'error')]
[(2, 'ok'), (4, 'fail'), (4, 'fail')]
[(2, 'ok'), (4, 'fail'), (4, 'error')]
[(2, 'ok'), (4, 'error'), (4, 'error')]
but y want this:
[(2, 'ok'), (3, 'ok'), (4, 'ok')]
[(2, 'ok'), (3, 'ok'), (4, 'fail')]
[(2, 'ok'), (3, 'ok'), (4, 'error')]
[(2, 'ok'), (3, 'fail'), (4, 'ok')]
[(2, 'ok'), (3, 'fail'), (4, 'fail')]
[(2, 'ok'), (3, 'fail'), (4, 'error')]
[(2, 'ok'), (3, 'error'), (4, 'ok')]
[(2, 'ok'), (3, 'error'), (4, 'fail')]
[(2, 'ok'), (3, 'error'), (4, 'error')]
Thanks in advance!
PS: The len
of the original lst
can be > 1000
lst = [(2, 'ok'), (3, 'ok'), (3, 'fail'), (3, 'error'), .... (n, 'ok'), (n, 'fail'), (n, 'error')]
CodePudding user response:
You could group items with the same number and later use itertool.product()
import itertools
lst = [(2, 'ok'), (3, 'ok'), (3, 'fail'), (3, 'error'), (4, 'ok'), (4, 'fail'), (4, 'error')]
groups = {}
for number, word in lst:
if number not in groups:
groups[number] = []
groups[number].append( (number, word) )
data = groups.values()
for item in itertools.product(*data):
print(item)
Result:
((2, 'ok'), (3, 'ok'), (4, 'ok'))
((2, 'ok'), (3, 'ok'), (4, 'fail'))
((2, 'ok'), (3, 'ok'), (4, 'error'))
((2, 'ok'), (3, 'fail'), (4, 'ok'))
((2, 'ok'), (3, 'fail'), (4, 'fail'))
((2, 'ok'), (3, 'fail'), (4, 'error'))
((2, 'ok'), (3, 'error'), (4, 'ok'))
((2, 'ok'), (3, 'error'), (4, 'fail'))
((2, 'ok'), (3, 'error'), (4, 'error'))
EDIT:
You may also use itertools.groupby(lst, lambda x:x[0])
to group items.
import itertools
lst = [(2, 'ok'), (3, 'ok'), (3, 'fail'), (3, 'error'), (4, 'ok'), (4, 'fail'), (4, 'error')]
groups = itertools.groupby(lst, lambda x:x[0])
data = [list(val) for key, val in groups]
#keys, data = zip(*groups) # ???
for item in itertools.product(*data):
print(item)
CodePudding user response:
Let's break down what you need here in a few steps.
Firstly, you will need to create all the combinations from the list of tuples.
from itertools import combinations
allcomb = combinations(lst,3)
Next, you will need to filter the combinations in which the first element has a two in it.
first = [i for i in allcomb if (2, 'ok') in i]
which is the same result as what you have tried. Finally, you will need to filter out the combinations where the first element in the tuple is distinct from one another.
second = [i for i in first if len(set(list(zip(*i))[0])) == 3]
[((2, 'ok'), (3, 'ok'), (4, 'ok')),
((2, 'ok'), (3, 'ok'), (4, 'fail')),
((2, 'ok'), (3, 'ok'), (4, 'error')),
((2, 'ok'), (3, 'fail'), (4, 'ok')),
((2, 'ok'), (3, 'fail'), (4, 'fail')),
((2, 'ok'), (3, 'fail'), (4, 'error')),
((2, 'ok'), (3, 'error'), (4, 'ok')),
((2, 'ok'), (3, 'error'), (4, 'fail')),
((2, 'ok'), (3, 'error'), (4, 'error'))]