length index comprehension python list

python - index - Obtener el producto cartesiano de una serie de listas?



python list to string (10)

Aquí hay un generador recursivo, que no almacena ninguna lista temporal

def product(ar_list): if not ar_list: yield () else: for a in ar_list[0]: for prod in product(ar_list[1:]): yield (a,)+prod print list(product([[1,2],[3,4],[5,6]]))

Salida:

[(1, 3, 5), (1, 3, 6), (1, 4, 5), (1, 4, 6), (2, 3, 5), (2, 3, 6), (2, 4, 5), (2, 4, 6)]

¿Cómo puedo obtener el producto cartesiano (cada posible combinación de valores) de un grupo de listas?

Entrada:

somelists = [ [1, 2, 3], [''a'', ''b''], [4, 5] ]

Salida deseada:

[(1, ''a'', 4), (1, ''a'', 5), (1, ''b'', 4), (1, ''b'', 5), (2, ''a'', 4), (2, ''a'', 5) ...]


Aunque ya hay muchas respuestas, me gustaría compartir algunos de mis pensamientos:

Enfoque iterativo

def cartesian_iterative(pools): result = [[]] for pool in pools: result = [x+[y] for x in result for y in pool] return result

Enfoque Recursivo

def cartesian_recursive(pools): if len(pools) > 2: pools[0] = product(pools[0], pools[1]) del pools[1] return cartesian_recursive(pools) else: pools[0] = product(pools[0], pools[1]) del pools[1] return pools def product(x, y): return [xx + [yy] if isinstance(xx, list) else [xx] + [yy] for xx in x for yy in y]

Enfoque Lambda

def cartesian_reduct(pools): return reduce(lambda x,y: product(x,y) , pools)


En Python 2.6 y superiores puedes usar ''itertools.product`. En versiones anteriores de Python puede usar el siguiente código equivalente (casi, ver documentación) de la documentación , al menos como punto de partida:

def product(*args, **kwds): # product(''ABCD'', ''xy'') --> Ax Ay Bx By Cx Cy Dx Dy # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111 pools = map(tuple, args) * kwds.get(''repeat'', 1) result = [[]] for pool in pools: result = [x+[y] for x in result for y in pool] for prod in result: yield tuple(prod)

El resultado de ambos es un iterador, por lo que si realmente necesita una lista para el procesamiento adicional, utilice la list(result) .



Para Python 2.5 y mayores:

>>> [(a, b, c) for a in [1,2,3] for b in [''a'',''b''] for c in [4,5]] [(1, ''a'', 4), (1, ''a'', 5), (1, ''b'', 4), (1, ''b'', 5), (2, ''a'', 4), (2, ''a'', 5), (2, ''b'', 4), (2, ''b'', 5), (3, ''a'', 4), (3, ''a'', 5), (3, ''b'', 4), (3, ''b'', 5)]

Aquí hay una versión recursiva del product() (solo una ilustración):

def product(*args): if not args: return iter(((),)) # yield tuple() return (items + (item,) for items in product(*args[:-1]) for item in args[-1])

Ejemplo:

>>> list(product([1,2,3], [''a'',''b''], [4,5])) [(1, ''a'', 4), (1, ''a'', 5), (1, ''b'', 4), (1, ''b'', 5), (2, ''a'', 4), (2, ''a'', 5), (2, ''b'', 4), (2, ''b'', 5), (3, ''a'', 4), (3, ''a'', 5), (3, ''b'', 4), (3, ''b'', 5)] >>> list(product([1,2,3])) [(1,), (2,), (3,)] >>> list(product([])) [] >>> list(product()) [()]


Solo para agregar un poco a lo que ya se ha dicho: si usas sympy, puedes usar símbolos en lugar de cadenas, lo que los hace matemáticamente útiles.

import itertools import sympy x, y = sympy.symbols(''x y'') somelist = [[x,y], [1,2,3], [4,5]] somelist2 = [[1,2], [1,2,3], [4,5]] for element in itertools.product(*somelist): print element

Acerca de sympy .


Una modificación menor de la solución del generador recursivo anterior en variadic sabor:

def product_args(*args): if args: for a in args[0]: for prod in product_args(*args[1:]) if args[1:] else ((),): yield (a,) + prod

Y, por supuesto, una envoltura que hace que funcione exactamente igual que esa solución:

def product2(ar_list): """ >>> list(product(())) [()] >>> list(product2(())) [] """ return product_args(*ar_list)

con una compensación : comprueba si la recursión debería interrumpirse en cada bucle externo, y una ganancia : no hay rendimiento en una llamada vacía, por ejemplo, product(()) , que supongo que sería semánticamente más correcta (consulte el doctest).

Con respecto a la comprensión de la lista: la definición matemática se aplica a un número arbitrario de argumentos, mientras que la comprensión de la lista solo podría tratar con un número conocido de ellos.


Yo usaría la lista de comprensión:

somelists = [ [1, 2, 3], [''a'', ''b''], [4, 5] ] cart_prod = [(a,b,c) for a in somelists[0] for b in somelists[1] for c in somelists[2]]


con itertools.product

import itertools result = list(itertools.product(*somelists))


import itertools >>> for i in itertools.product([1,2,3],[''a'',''b''],[4,5]): ... print i ... (1, ''a'', 4) (1, ''a'', 5) (1, ''b'', 4) (1, ''b'', 5) (2, ''a'', 4) (2, ''a'', 5) (2, ''b'', 4) (2, ''b'', 5) (3, ''a'', 4) (3, ''a'', 5) (3, ''b'', 4) (3, ''b'', 5) >>>