2

I have a list of lists of tuples

A= [ [(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)] ]

The outer list can have any number of inner lists, the inner lists can have any number of tuples, a tuple always has 3 integers.

I want to generate all combination of tuples, one from each list:

[(1,2,3),(7,8,9),(2,1,0)]
[(1,2,3),(7,8,9),(1,3,5)]
[(1,2,3),(8,7,6),(2,1,0)]
...
[(4,5,6),(5,4,3),(1,3,5)]

A simple way to do it is to use a function similar to itertools.poduct() but it must be called like this

itertools.product([(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)])

i.e the outer list is removed. And I don't know how to do that. Is there a better way to generate all combinations of tuples?

Dominic Rodger
  • 97,747
  • 36
  • 197
  • 212
lgwest
  • 1,347
  • 5
  • 16
  • 26
  • How deep can the nested levels of lists be. Just 2, as in your example? – Kenan Banks Nov 06 '09 at 16:34
  • Duplicate: http://stackoverflow.com/search?q=%5Bpython%5D+flatten, http://stackoverflow.com/questions/120886/python-idiom-to-chain-flatten-an-infinite-iterable-of-finite-iterables, http://stackoverflow.com/questions/406121/flattening-a-shallow-list-in-python – S.Lott Nov 06 '09 at 16:38
  • @S Lott, related but not duplicates. (I thought so too, initially, the "flatten" keyword is misleading I think. Thought of editing title but didn't find a better expression; maybe "enumerate combinations"... – mjv Nov 06 '09 at 16:45
  • Maybe wrong word, but thought it was about "flatten" when I wrote the question. No, it is not homework. I got my degree '83, been working sice then. But new with python. trying to solve a quiz in a swedish newspaper lead to all my questions so far. – lgwest Nov 06 '09 at 16:59
  • 2
    "Cartesian product" is maybe the word you're looking for. – Thomas Nov 08 '09 at 20:27

7 Answers7

10
itertools.product(*A)

For more details check the python tutorial

Nadia Alramli
  • 111,714
  • 37
  • 173
  • 152
2

This works for your example, if there is only one level of nested lists (no lists of lists of lists):

itertools.product(*A)
Kenan Banks
  • 207,056
  • 34
  • 155
  • 173
2

you can probably call itertools.product like so:

itertools.product(*A) # where A is your list of lists of tuples

This way it expands your list's elements into arguments for the function you are calling.

Lesmana
  • 25,663
  • 9
  • 82
  • 87
Kevlar
  • 8,804
  • 9
  • 55
  • 81
2

Late to the party but ...

I'm new to python and come from a lisp background. This is what I came up with (check out the var names for lulz):

def flatten(lst):
    if lst:
        car,*cdr=lst
        if isinstance(car,(list)):
            if cdr: return flatten(car) + flatten(cdr)
            return flatten(car)
        if cdr: return [car] + flatten(cdr)
        return [car]

Seems to work. Test:

A = [ [(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)] ]

flatten(A)

Result:

[(1, 2, 3), (4, 5, 6), (7, 8, 9), (8, 7, 6), (5, 4, 3), (2, 1, 0), (1, 3, 5)]

Note: the line car,*cdr=lst only works in Python 3.0

Lesmana
  • 25,663
  • 9
  • 82
  • 87
Michael Puckett
  • 465
  • 1
  • 5
  • 7
  • -1 The statement ``car,*cdr=lst`` isn't even legal Python. There is no direct syntax in Python to split a list in its head and tail (sorry 'bout that). – ThomasH Apr 29 '11 at 08:32
  • @ThomasH: It *is* valid in Python 3. See http://www.python.org/dev/peps/pep-3132/. +1 to counteract needless downvote. – Steven Rumbalski Oct 25 '11 at 21:18
  • @StevenRumbalski Thanks for the pointer. I thought I was checking the Python 3 docs too, but obviously missed the `*target`. – ThomasH Oct 26 '11 at 16:41
1

This is not exactly one step, but this would do what you want if for some reason you don't want to use the itertools solution:

def crossprod(listoflists):
    if len(listoflists) == 1:
        return listoflists
    else:
        result = []
        remaining_product = prod(listoflists[1:])
        for outertupe in listoflists[0]:
            for innercombo in remaining_product[0]:
                newcombo = [outertupe]
                newcombo.append(innercombo)
                result.append(newcombo)
        return result
dsimard
  • 4,245
  • 5
  • 22
  • 16
1
def flatten(A)
    answer = []
    for i in A:
        if type(i) == list:
            ans.extend(i)
        else:
            ans.append(i)
    return ans
Lesmana
  • 25,663
  • 9
  • 82
  • 87
inspectorG4dget
  • 110,290
  • 27
  • 149
  • 241
-1

This may also be achieved using list comprehension.

In [62]: A = [ [(1,2,3),(4,5,6)], [(7,8,9),(8,7,6),(5,4,3)],[(2,1,0),(1,3,5)] ]

In [63]: improved_list = [num for elem in A for num in elem]

In [64]: improved_list
Out[64]: [(1, 2, 3), (4, 5, 6), (7, 8, 9), (8, 7, 6), (5, 4, 3), (2, 1, 0), (1, 3, 5)]
jcubic
  • 61,973
  • 54
  • 229
  • 402
ronak
  • 1,770
  • 3
  • 20
  • 34