Cartesian Product of two lists (itertools)

Discussion in 'Python' started by Thorsten Kampe, Jan 25, 2009.

  1. 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
     
    Thorsten Kampe, Jan 25, 2009
    #1
    1. Advertising

  2. Thorsten Kampe

    Mensanator Guest

    On Jan 25, 3:12�pm, 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:
    >
    > 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)]
    >>>
     
    Mensanator, Jan 25, 2009
    #2
    1. Advertising

  3. Thorsten Kampe

    Terry Reedy Guest

    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))
     
    Terry Reedy, Jan 26, 2009
    #3
  4. Thorsten Kampe

    Mark Wooding Guest

    Thorsten Kampe <> 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]
     
    Mark Wooding, Jan 26, 2009
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. deancoo

    cartesian product...

    deancoo, Feb 28, 2005, in forum: C++
    Replies:
    4
    Views:
    2,340
    Matt Bitten
    Feb 28, 2005
  2. Cartesian product

    , Feb 11, 2007, in forum: C++
    Replies:
    2
    Views:
    987
    Kai-Uwe Bux
    Feb 11, 2007
  3. Brad
    Replies:
    9
    Views:
    375
  4. walter a kehowski

    cartesian product

    walter a kehowski, Aug 7, 2005, in forum: Ruby
    Replies:
    26
    Views:
    337
    tony summerfelt
    Aug 10, 2005
  5. walter a kehowski

    cartesian product - next to last version

    walter a kehowski, Aug 11, 2005, in forum: Ruby
    Replies:
    11
    Views:
    221
    Brian Schröder
    Aug 13, 2005
Loading...

Share This Page