Pregunta ¿Comprende la lista recursiva en Python?


¿Es posible definir una lista recursiva de comprensión en Python?

Posiblemente un ejemplo simplista, pero algo como:

nums = [1, 1, 2, 2, 3, 3, 4, 4]
willThisWork = [x for x in nums if x not in self] # self being the current comprehension

¿Es posible algo como esto?


32
2018-04-14 15:03


origen


Respuestas:


No, no hay manera (documentada, sólida, estable, ... ;-) de referirse a "la comprensión actual". Podrías usar un bucle:

res = []
for x in nums:
  if x not in res:
    res.append(x)

por supuesto, esto es muy costoso (O (N al cuadrado)), por lo que puede optimizarlo con un auxiliar set (Estoy asumiendo que mantener el orden de los artículos en res congruente con el de los elementos en numsDe lo contrario set(nums) te haría; -) ...:

res = []
aux = set()
for x in nums:
  if x not in aux:
    res.append(x)
    aux.add(x)

esto es mucho más rápido para listas muy largas (O (N) en lugar de N al cuadrado).

Editar: en Python 2.5 o 2.6, vars()['_[1]'] en realidad podría funcionar en el rol que desea para self (para un listcomp no anidado) ... por lo que califiqué mi declaración aclarando que no hay documentado, sólido, estable forma de acceder a "la lista que se está creando" - ese "nombre" peculiar e indocumentado '_[1]' (elegido deliberadamente para no ser un identificador válido ;-) es el vértice de los "artefactos de implementación" y cualquier código que dependa de él merece ser sacado de su miseria ;-).


32
2018-04-14 15:08



¡En realidad puedes! Este ejemplo con una explicación con suerte ilustrará cómo.

defina el ejemplo recursivo para obtener un número solo cuando es 5 o más y, en caso contrario, increméntelo y vuelva a llamar a la función 'verificar'. Repite este proceso hasta que llegue a 5, en cuyo punto regresa 5.

print [ (lambda f,v: v >= 5 and v or f(f,v+1))(lambda g,i: i >= 5 and i or g(g,i+1),i) for i in [1,2,3,4,5,6] ]

resultado:

[5, 5, 5, 5, 5, 6]
>>> 

esencialmente las dos funciones anónimas interactúan de esta manera:

let f(g,x) = {  
                 expression, terminal condition
                 g(g,x), non-terminal condition
             }

let g(f,x) = {  
                 expression, terminal condition
                 f(f,x), non-terminal condition
             }

make g, f la 'misma' función excepto que en uno o ambos agregue una cláusula donde el parámetro se modifique para hacer que se alcance la condición del terminal y luego ir f (g, x) de esta manera g se convierte en una copia de f por lo que es:

f(g,x) = {  
                 expression, terminal condition
                 {
                    expression, terminal condition,
                    g(g,x), non-terminal codition
                 }, non-terminal condition
             }

Debe hacer esto porque no puede acceder a la función anónima al momento de la ejecución.

es decir

(lambda f,v: somehow call the function again inside itself )(_,_)

entonces en este ejemplo, deje A = la primera función y B la segunda. Llamamos a A pasando B como f y yo como v. Ahora, como B es esencialmente una copia de A y es un parámetro que ya ha pasado, ahora puede llamar a B, que es como llamar a A.

Esto genera los factoriales en una lista

print [ (lambda f,v: v == 0 and 1 or v*f(f,v-1))(lambda g,i: i == 0 and 1 or i*g(g,i-1),i) for i in [1,2,3,5,6,7] ]

[1, 2, 6, 120, 720, 5040]
>>> 

10
2017-08-11 12:35



no. no funcionará, no hay self para referirse mientras se está ejecutando la comprensión de la lista.

Y la razón principal por supuesto es que las listas de comprensión no están diseñadas para este uso.


1
2018-04-14 15:05



No estoy seguro de si esto es lo que quiere, pero puede escribir listas anidadas de comprensión:

xs = [[i for i in range(1,10) if i % j == 0] for j in range(2,5)]
assert xs == [[2, 4, 6, 8], [3, 6, 9], [4, 8]]

Desde su ejemplo de código, parece que desea simplemente eliminar duplicados, lo que puede hacer con conjuntos:

xs = sorted(set([1, 1, 2, 2, 3, 3, 4, 4]))
assert xs == [1, 2, 3, 4]

1
2018-04-14 15:07



No.

Pero parece que estás tratando de hacer una lista de los elementos únicos en nums.

Puedes usar un set:

unique_items = set(nums)

Tenga en cuenta que los elementos en nums deben ser lavables.

También puedes hacer lo siguiente. Que es lo más cerca que puedo llegar a tu idea original. Pero esto no es tan eficiente como crear un set.

unique_items = []
for i in nums:
    if i not in unique_items:
        unique_items.append(i)

1
2018-04-14 15:08



Hacer esto:

nums = [1, 1, 2, 2, 3, 3, 4, 4]
set_of_nums = set(nums)
unique_num_list = list(set_of_nums)

o incluso esto:

unique_num_list = sorted(set_of_nums)

1
2018-04-14 20:14