Al procesar una lista usando map(), quiero acceder al índice del elemento mientras estoy dentro de lambda. ¿Cómo puedo hacer eso?
Por ejemplo
ranked_users = ['jon','bob','jane','alice','chris']
user_details = map(lambda x: {'name':x, 'rank':?}, ranked_users)
¿Cómo puedo obtener el rango de cada usuario en el ejemplo anterior?
unutbu
Usar enumerar:
In [3]: user_details = [{'name':x, 'rank':i} for i,x in enumerate(ranked_users)]
In [4]: user_details
Out[4]:
[{'name': 'jon', 'rank': 0},
{'name': 'bob', 'rank': 1},
{'name': 'jane', 'rank': 2},
{'name': 'alice', 'rank': 3},
{'name': 'chris', 'rank': 4}]
PD. mi primera respuesta fue
user_details = map(lambda (i,x): {'name':x, 'rank':i}, enumerate(ranked_users))
Recomiendo enfáticamente usar una comprensión de lista o una expresión generadora sobre map
y lambda
cuando sea posible. Las listas de comprensión son más legibles y tienden a ser más rápidas de iniciar.
-
¿Los parámetros de lambda no deberían estar sin paréntesis?
– dinosaurio
25 de marzo de 2011 a las 13:16
-
@dheerosaur No en este caso, ya que la operación next() en enumerate devuelve una tupla. Esta lambda es equivalente a def foo((i,x))
– Varilla
25 de marzo de 2011 a las 13:20
-
@dheerosaur: En realidad, los paréntesis son obligatorios.
enumerate
genera tuplas (un solo objeto).– unutbu
25 de marzo de 2011 a las 13:21
-
@Rod, @unutbu: Lo tengo. Asi que,
lambda
s no puede desempaquetar tuplas como lo hacen las listas por comprensión.– dinosaurio
25 de marzo de 2011 a las 13:32
-
@dheerosaur: Sí, las lambdas se desempaquetan de manera diferente a las listas de comprensión (en Python2). Tenga en cuenta que en Python3, las lambdas se niegan a desempaquetar: consulte diveintopython3.org/….
– unutbu
25 de marzo de 2011 a las 14:10
Prydie
Alternativamente, podría usar un lista de comprensión en lugar de map() y lambda.
ranked_users = ['jon','bob','jane','alice','chris']
user_details = [{'name' : x, 'rank' : ranked_users.index(x)} for x in ranked_users]
Producción:
[{'name': 'jon', 'rank': 0}, {'name': 'bob', 'rank': 1}, {'name': 'jane', 'rank': 2}, {'name': 'alice', 'rank': 3}, {'name': 'chris', 'rank': 4}]
Las listas de comprensión son muy poderosas y también son más rápidas que una combinación de map
y lambda
.
-
list.index()
sólo es apropiado si todos los miembros deranked_users
son únicos. Dadoranked_users = ['chris','chris']
user_details
salidas[{'name': 'chris', 'rank': 0}, {'name': 'chris', 'rank': 0}]
donde debería estar[{'name': 'chris', 'rank': 0}, {'name': 'chris', 'rank': 1}]
.– este geek
25 de noviembre de 2012 a las 15:51
-
Sin embargo, solo tendría sentido (dados estos datos) que los miembros fueran únicos…
– Pridie
29 de noviembre de 2012 a las 11:39
-
Por supuesto. Tu respuesta se ajusta al ejemplo. Simplemente pensé que sería una buena idea indicar la advertencia de singularidad para cualquier persona que se encuentre con esta publicación.
– este geek
29 de noviembre de 2012 a las 18:27
-
el uso de la llamada de función de índice en la lista de usuarios clasificados está un poco sobrediseñado. Python para la expresión itera sobre objetos en la estructura de datos
– gato de Cheshire
16 de agosto de 2019 a las 17:10
gato de Cheshire
En mi opinión, la pregunta era sobre la función del mapa y la respuesta preferida es parcialmente correcta debido a un error de sintaxis causado al poner un argumento de tupla a lambda lambda (i,x)
la idea de enumerar es agradable y la solución adecuada sería:
map(lambda x: {'name':x[1], 'rank':x[0]}, enumerate(ranked_users))
y algunos tiempos para comparar la velocidad con la comprensión:
def with_map():
ranked_users = range(10 ** 6)
list(map(lambda x: {'name': x[1], 'rank': x[0]}, enumerate(ranked_users)))
def by_comprehension():
ranked_users = range(10 ** 6)
[{'name': x, 'rank': i} for i, x in enumerate(ranked_users)]
from timeit import timeit
time_with_map = timeit(with_map, number=10)
time_with_comprehension = timeit(by_comprehension, number=10)
print('list comprehension is about %.2f x faster than map in this test case' % (time_with_map/time_with_comprehension))
resultado de la prueba: la comprensión de la lista es aproximadamente 1,31 veces más rápida que la del mapa en este caso de prueba
xbalaj
En realidad, aquí hay una solución más elegante y detallada que usar una tupla enumerada en el mapa (debido a la indexación de tupla). El mapa puede tomar más iterables como argumentos, así que usémoslo.
map(lambda user, user_id: (user_id, user), ranked_users, range(ranked_users.__len__()))