2010-01-03 7 views
15

¿Hay alguna forma de asignar una lista a un diccionario? Lo que quiero hacer es darle una función que devolverá el nombre de una clave, y el valor será el valor original. Por ejemplo;Lista de mapas en el diccionario

somefunction(lambda a: a[0], ["hello", "world"]) 
=> {"h":"hello", "w":"world"} 

(Esto no es un ejemplo específico que yo quiero hacer, quiero una función genérica como map() que puede hacer esto)

Respuesta

22

no creo que exista una función estándar que hace exactamente eso , pero es muy fácil de construir uno usando el dict orden interna y una comprensión:

def somefunction(keyFunction, values): 
    return dict((keyFunction(v), v) for v in values) 

print somefunction(lambda a: a[0], ["hello", "world"]) 

salida:

{'h': 'hello', 'w': 'world'} 

Pero crear un buen nombre para esta función es más difícil que implementarlo. Lo dejo como un ejercicio para el lector.

+0

Estoy usando esto en un programa de código abierto, bajo una licencia de estilo BSD. Te di crédito, ¿solo quieres asegurarte de que estás de acuerdo con eso? –

+2

Estoy de acuerdo con eso, pero me sorprende que otorgue crédito explícito por una contribución tan pequeña. –

+0

@MarkByers, Nice, gracias! – user1514631

5

Si entiendo bien su pregunta, creo que se puede lograr esto con una combinación de map, zip y la dict constructor:

def dictMap(f, xs) : 
    return dict(zip(map(f, xs), xs) 

Y una implementación más sano:

def dictMap(f, xs) : 
    return dict((f(i), i) for i in xs) 
+0

Esta solución también funciona en 2.7.5. –

22

En Python 3 puede usar esta sintaxis de comprensión del diccionario:

def foo(somelist): 
    return {x[0]:x for x in somelist} 
+3

Esta sintaxis también está disponible en python 2.7 –

1

Si quieres una función general para hacer esto, entonces estás haciendo casi la pregunta correcta. Sin embargo, su ejemplo no especifica qué sucede cuando la función clave produce duplicados. ¿Conservas el último? ¿El primero? ¿Realmente desea hacer una lista de todas las palabras que comienzan con la misma letra? Es probable que el usuario de la función responda mejor estas preguntas, no el diseñador.

Parametrizar estos resultados en una función más complicada, pero muy general. Aquí hay uno que he utilizado desde hace varios años:

def reduce_list(key, update_value, default_value, l): 
    """Reduce a list to a dict. 

    key :: list_item -> dict_key 
    update_value :: key * existing_value -> updated_value 
    default_value :: initial value passed to update_value 
    l :: The list 

    default_value comes before l. This is different from functools.reduce, 
    because functools.reduce's order is wrong. 
    """ 
    d = {} 
    for k in l: 
     j = key(k) 
     d[j] = update_value(k, d.get(j, default_value)) 
    return d 

Entonces usted puede escribir su función diciendo:

reduce_list(lambda s:s, lambda s,old:s[0], '', ['hello', 'world']) 
# OR 
reduce_list(lambda s:s, lambda s,old: old or s[0], '', ['hello', 'world']) 

Dependiendo de si se desea mantener la primera o la última palabra que empiece con, por ejemplo, 'h'.

Esta función es muy general, sin embargo, por lo que la mayor parte de las veces es la base para otras funciones, como group_dict o histogram:

def group_dict(l): 
    return reduce_list(lambda x:x, lambda x,old: [x] + old, [], l) 
def histogram(l): 
    return reduce_list(lambda x:x, lambda x,total: total + 1, 0, l) 
1
>>> dict((a[0], a) for a in "hello world".split()) 
{'h': 'hello', 'w': 'world'} 

Si desea utilizar una función en lugar de subíndices, utilizar operator.itemgetter:

>>> from operator import itemgetter 
>>> first = itemgetter(0) 
>>> dict((first(x), x) for x in "hello world".split()) 
{'h': 'hello', 'w': 'world'} 

o como una función:

>>> dpair = lambda x : (first(x), x) 
>>> dict(dpair(x) for x in "hello world".split()) 
{'h': 'hello', 'w': 'world'} 

Por último, si desea más de una palabra por cada una de las letras, use las colecciones.defaultdict

>>> from collections import defaultdict 
>>> words = defaultdict(set) 
>>> addword = lambda x : words[first(x)].add(x) 
>>> for word in "hello house home hum world wry wraught".split(): 
     addword(word) 


>>> print words['h'] 
set(['house', 'hello', 'hum', 'home']) 
0

Tomando indicios de otras respuestas Logré esto usando la operación del mapa. No estoy seguro de si esto responde exactamente su pregunta.

mylist = ["hello", "world"] 
def convert_to_dict(somelist): 
    return dict(map(lambda x: (x[0], x), somelist)) 

final_ans = convert_to_dict(mylist) 
print final_ans 
Cuestiones relacionadas