2012-05-21 26 views
5

Estoy tratando de usar map() en el objeto dict_values devuelto por la función values() en un diccionario. Sin embargo, me parece que no puede ser capaz de map() durante un dict_values:Python map() valores del diccionario

map(print, h.values()) 
Out[31]: <builtins.map at 0x1ce1290> 

Estoy seguro de que hay una manera fácil de hacer esto. Lo que en realidad estoy tratando de hacer es crear un set() de todas las teclas Counter en un diccionario de Counters, haciendo algo como esto:

# counters is a dict with Counters as values 
whole_set = set() 
map(lambda x: whole_set.update(set(x)), counters.values()) 

¿Hay una mejor manera de hacer esto en Python?

+0

tratar de dar ejemplo de entrada/salida - hace que sea mucho más fácil ver lo que está tratando de lograr. –

+0

No sé si le importa el primer ejemplo, pero esto es equivalente: 'print (* h.values ​​(), sep = '\ n')' a una versión del mapa sin generador. – Darthfett

Respuesta

13

En Python 3, map devuelve un iterador, no una lista. Aún debe iterar sobre él, ya sea llamando al list explícitamente o poniéndolo en un bucle for. Pero no debe usar map de esta manera de todos modos. map es realmente para recopilar valores devueltos en una secuencia o iterable. Como ni print ni set.update devuelve un valor, usar map en este caso no es idiomático.

Su objetivo es poner todas las llaves en todos los contadores en counters en un solo conjunto. Una forma de hacerlo es utilizar una expresión generadora anidada:

s = set(key for counter in counters.values() for key in counter) 

También existe la sintaxis de la comprensión dict preciosa, que está disponible en Python 2.7 y superior (gracias Lattyware!) Y puede generar conjuntos, así como los diccionarios:

s = {key for counter in counters.values() for key in counter} 

Estos son tanto más o menos equivalente a lo siguiente:

s = set() 
for counter in counters.values(): 
    for key in counter: 
     s.add(key) 
+0

Perfecto, eso es exactamente lo que estaba buscando. ¡Muchas gracias! –

+2

Tenga en cuenta que la opción ligeramente más clara aquí es simplemente usar una comprensión de conjunto, en lugar de una expresión de generador en el constructor de conjunto - '{clave para contador en contadores.valores() para clave en contador}'. –

0

desea que el set-unión de todos los valores de counters? Es decir,

counters[1].union(counters[2]).union(...).union(counters[n]) 

? Eso es sólo functools.reduce:

import functools 

s = functools.reduce(set.union, counters.values()) 


Si counters.values() no son ya fija (por ejemplo, si están listas), entonces usted debe convertirlos en conjuntos primero. Puede hacerlo utilizando un dict comprehension usando iteritems, que es un poco torpe:

>>> counters = {1:[1,2,3], 2:[4], 3:[5,6]} 
>>> counters = {k:set(v) for (k,v) in counters.iteritems()} 
>>> print counters 
{1: set([1, 2, 3]), 2: set([4]), 3: set([5, 6])} 

o, por supuesto que puede hacerlo en línea, ya que no se preocupan por counters.keys():

>>> counters = {1:[1,2,3], 2:[4], 3:[5,6]} 
>>> functools.reduce(set.union, [set(v) for v in counters.values()]) 
set([1, 2, 3, 4, 5, 6]) 
Cuestiones relacionadas