Soy un novato en Python que intenta lograr lo siguiente:
Tengo una lista de listas:
lst = [[567,345,234],[253,465,756, 2345],[333,777,111, 555]]
Quiero mapear lst en otra lista que contenga solo el segundo número más pequeño de cada sublista. Entonces el resultado debería ser:
[345, 465, 333]
Por ejemplo, si solo estuviera interesado en el número más pequeño, podría hacer:
map(lambda x: min(x),lst)
Ojalá pudiera hacer esto:
map(lambda x: sort(x)[1],lst)
pero el género no encadena. (devuelve Ninguno)
tampoco se permite algo como esto:
map(lambda x: sort(x); x[1],lst) #hence the multiple statement question
¿Hay alguna manera de hacer esto con map en python pero sin definir una función con nombre ? (es fácil con bloques anónimos en ruby, por ejemplo)
lambda x: sort(x) OR x[1]
funcionaría: aquí el OR evalúa su primer argumento (valor de retorno Ninguno) como un bool (=> Falso), y en ese caso OR devuelve su segundo argumento. Pero como dicen las respuestas, es mejor evitar lambda.Respuestas:
Hay varias respuestas diferentes que puedo dar aquí, desde su pregunta específica hasta preocupaciones más generales. Entonces, de lo más específico a lo más general:
P. ¿Puede poner varias declaraciones en una lambda?
R. No. Pero en realidad no es necesario utilizar una lambda. Puede poner las declaraciones en un
def
. es decir:P. ¿Puede obtener el segundo elemento más bajo de una lambda ordenando la lista?
R. Sí. Como señala la respuesta de Alex,
sorted()
es una versión de sort que crea una nueva lista, en lugar de ordenar en el lugar, y se puede encadenar. Tenga en cuenta que esto es probablemente lo que debería usar; es una mala práctica que su mapa tenga efectos secundarios en la lista original.P. ¿Cómo debo obtener el segundo elemento más bajo de cada lista en una secuencia de listas?
A.
sorted(l)[1]
no es realmente la mejor manera de hacerlo. Tiene una complejidad O (N log (N)), mientras que existe una solución O (n). Esto se puede encontrar en el módulo heapq.Así que solo usa:
También se suele considerar más claro usar una lista de comprensión, que evita la lambda por completo:
fuente
k
(como aquí con 'segundo más bajo') seO(k*log(n)+n)
simplifica aO(n)
Poner las declaraciones en una lista puede simular varias declaraciones:
P.ej:
fuente
None
.Viajero del tiempo aquí. Si generalmente desea tener varias declaraciones dentro de una lambda, puede pasar otras lambdas como argumentos a esa lambda.
En realidad, no puede tener varias declaraciones, pero puede simular eso pasando lambdas a lambdas.
Editar: ¡ El viajero del tiempo regresa! También puede abusar del comportamiento de las expresiones booleanas (teniendo en cuenta las reglas de cortocircuito y la veracidad) para encadenar operaciones. El uso del operador ternario le brinda aún más potencia. Una vez más, no puede tener varias declaraciones , pero, por supuesto, puede tener muchas llamadas a funciones. Este ejemplo hace basura arbitraria con un montón de datos, pero muestra que puedes hacer cosas divertidas. Las declaraciones de impresión son ejemplos de funciones que regresan
None
(al igual que el.sort()
método) pero también ayudan a mostrar lo quelambda
está haciendo.fuente
Utilice una función ordenada , como esta:
fuente
[sorted(x)[1] for x in list_of_lists]
.De hecho, puede tener varias declaraciones en una expresión lambda en Python. No es del todo trivial, pero en su ejemplo, lo siguiente funciona:
Debe asegurarse de que cada declaración no devuelva nada o si lo envuelve (.. y False). El resultado es lo que devuelve la última evaluación.
Ejemplo:
fuente
Usando begin () desde aquí: http://www.reddit.com/r/Python/comments/hms4z/ask_pyreddit_if_you_were_making_your_own/c1wycci
fuente
Una forma de Hacky de combinar varias declaraciones en una sola declaración en Python es usar la palabra clave "y" como operador de cortocircuito. Luego, puede usar esta única declaración directamente como parte de la expresión lambda.
Esto es similar a usar "&&" como operador de cortocircuito en lenguajes de shell como bash.
También tenga en cuenta: siempre puede corregir una declaración de función para devolver un valor verdadero envolviendo la función.
Ejemplo:
Pensándolo bien, probablemente sea mejor usar 'o' en lugar de 'y' ya que muchas funciones devuelven '0' o Ninguno en caso de éxito. Entonces puede deshacerse de la función de contenedor en el ejemplo anterior:
'y' operar evaluarán las expresiones hasta que llegue al primer valor de retorno cero. después de lo cual se cortocircuita. 1 y 1 y 0 y 1 evalúa: 1 y 1 y 0, y elimina 1
'u' operar evaluará las expresiones hasta que llegue al primer valor de retorno distinto de cero. después de lo cual se cortocircuita.
0 o 0 o 1 o 0 evalúa 0 o 0 o 1, y elimina 0
fuente
O si desea evitar lambda y tener un generador en lugar de una lista:
(ordenado (col) [1] para col en lst)
fuente
Permítanme presentarles un truco glorioso pero aterrador:
Ahora puede utilizar este
LET
formulario como tal:lo que da:
[345, 465, 333]
fuente
Puede hacerlo en O (n) time usando min e index en lugar de usar sort o heapq.
Primero cree una nueva lista de todo excepto el valor mínimo de la lista original:
Luego toma el valor mínimo de la nueva lista:
Ahora todos juntos en una sola lambda:
Sí, es realmente feo, pero debería ser algorítmicamente barato. Además, dado que algunas personas en este hilo quieren ver listas por comprensión:
fuente
Esto es exactamente para lo que se utiliza la
bind
función en una mónada .Con la
bind
función puede combinar múltiples lambda en una lambda, cada lambda representa una declaración.fuente
De hecho, existe una forma de utilizar varias declaraciones en lambda. Esta es mi solución:
fuente
exec
no puede ser introspectado por un IDE inteligenteSi. Puede definirlo de esta manera y luego envolver sus múltiples expresiones con lo siguiente:
Comienzo del esquema:
comenzar = lambda * x: x [-1]
Pronóstico común de Lisp:
progn = lambda * x: x [-1]
fuente
Hay mejores soluciones sin usar la función lambda. Pero si realmente queremos usar la función lambda, aquí hay una solución genérica para lidiar con múltiples declaraciones: map (lambda x: x [1] if (x.sort ()) else x [1], lst)
Realmente no te importa lo que devuelve la declaración.
fuente
Sí, es posible. Pruebe el siguiente fragmento de código.
fuente
Te daré otra solución, haz que tu lambda invoque una función.
fuente
junky = multiple_statements
.