Cartesian Product of two lists (itertools)
Hi, is there a way to make itertools.product generate triples instead of pairs from two lists? For example: list1 = [1, 2]; list2 = [4, 5]; list3 = [7, 8] from itertools import product list(product(list1, list2, list3)) [(1, 4, 7), (1, 4, 8), (1, 5, 7), (1, 5, 8), (2, 4, 7), (2, 4, 8), (2, 5, 7), (2, 5, 8)] so far so good... Now... list(product(product(list1, list2), list3)) [((1, 4), 7), ((1, 4), 8), ((1, 5), 7), ((1, 5), 8), ((2, 4), 7), ((2, 4), 8), ((2, 5), 7), ((2, 5), 8)] Oops, pairs of pairs instead triples. Not what I wanted. What's the best way to pre-process the arguments to itertools.product or to post-process the result of itertools.product to get what I want?! I have an older utility which I would like to replace with itertools.product. The old one uses a rather clumsy way to indicate that a triple was wanted: def cartes(seq0, seq1, modus = 'pair'): return the Cartesian Product of two sequences if modus == 'pair': return [[item0, item1] for item0 in seq0 for item1 in seq1] elif modus == 'triple': return [item0 + [item1] for item0 in seq0 for item1 in seq1] Thorsten -- http://mail.python.org/mailman/listinfo/python-list
Re: Cartesian Product of two lists (itertools)
On Jan 25, 3:12�pm, Thorsten Kampe thors...@thorstenkampe.de wrote: Hi, is there a way to make itertools.product generate triples instead of pairs from two lists? For example: list1 = [1, 2]; list2 = [4, 5]; list3 = [7, 8] from itertools import product list(product(list1, list2, list3)) [(1, 4, 7), (1, 4, 8), (1, 5, 7), (1, 5, 8), (2, 4, 7), (2, 4, 8), (2, 5, 7), (2, 5, 8)] so far so good... Now... list(product(product(list1, list2), list3)) [((1, 4), 7), ((1, 4), 8), ((1, 5), 7), ((1, 5), 8), ((2, 4), 7), ((2, 4), 8), ((2, 5), 7), ((2, 5), 8)] Oops, pairs of pairs instead triples. Not what I wanted. What's the best way to pre-process the arguments to itertools.product or to post-process the result of itertools.product to get what I want?! I have an older utility which I would like to replace with itertools.product. The old one uses a rather clumsy way to indicate that a triple was wanted: def cartes(seq0, seq1, modus = 'pair'): � � return the Cartesian Product of two sequences � � if � modus == 'pair': � � � � return [[item0, item1] for item0 in seq0 for item1 in seq1] � � elif modus == 'triple': � � � � return [item0 + [item1] for item0 in seq0 for item1 in seq1] Thorsten Will this work for you? list4 = [(i,) for i in list3] list4 [(7,), (8,)] a = list(itertools.product(itertools.product(list1, list2), list4)) a [((1, 4), (7,)), ((1, 4), (8,)), ((1, 5), (7,)), ((1, 5), (8,)), ((2, 4), (7,)), ((2, 4), (8,)), ((2, 5), (7,)), ((2, 5), (8,))] def flatten(listOfLists): return tuple(itertools.chain.from_iterable(listOfLists)) list5 = [flatten(i) for i in a] list5 [(1, 4, 7), (1, 4, 8), (1, 5, 7), (1, 5, 8), (2, 4, 7), (2, 4, 8), (2, 5, 7), (2, 5, 8)] -- http://mail.python.org/mailman/listinfo/python-list
Re: Cartesian Product of two lists (itertools)
Thorsten Kampe wrote: Hi, is there a way to make itertools.product generate triples instead of pairs from two lists? For example: list1 = [1, 2]; list2 = [4, 5]; list3 = [7, 8] from itertools import product list(product(list1, list2, list3)) [(1, 4, 7), (1, 4, 8), (1, 5, 7), (1, 5, 8), (2, 4, 7), (2, 4, 8), (2, 5, 7), (2, 5, 8)] so far so good... Now... list(product(product(list1, list2), list3)) [((1, 4), 7), ((1, 4), 8), ((1, 5), 7), ((1, 5), 8), ((2, 4), 7), ((2, 4), 8), ((2, 5), 7), ((2, 5), 8)] Oops, pairs of pairs instead triples. Not what I wanted. What's the best way to pre-process the arguments to itertools.product or to post-process the result of itertools.product to get what I want?! I have an older utility which I would like to replace with itertools.product. The old one uses a rather clumsy way to indicate that a triple was wanted: A pair of function, cart_pair, cart_trip, would have been better. Or auto recognition of the number of sequences passed in. def cartes(seq0, seq1, modus = 'pair'): return the Cartesian Product of two sequences if modus == 'pair': return [[item0, item1] for item0 in seq0 for item1 in seq1] elif modus == 'triple': return [item0 + [item1] for item0 in seq0 for item1 in seq1] The second branch only produces a triple if seq0 is a sequence of pairs. This must be called with something like res = cartes(cartes(list1,list2),list3,'triple') Just replace that with your first only-once itertools call list(product(list1, list2, list3)) -- http://mail.python.org/mailman/listinfo/python-list
Re: Cartesian Product of two lists (itertools)
Thorsten Kampe thors...@thorstenkampe.de writes: [((1, 4), 7), ((1, 4), 8), ((1, 5), 7), ((1, 5), 8), ((2, 4), 7), ((2, 4), 8), ((2, 5), 7), ((2, 5), 8)] [...] What's the best way to pre-process the arguments to itertools.product or to post-process the result of itertools.product to get what I want?! Python has powerful destructuring capabilities: [(x, y, z) for ((x, y), z) in lopsided_list] This seems simpler and is probably faster than a generalized flatten for this size of problem, but I wouldn't use it to rearrange tuples with more than four or five elements. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list