2012-02-18 26 views
5

tengo un código que se ve algo como esto:Crear un diccionario de Python que contiene pares de valores clave específicas de otro diccionario

d = {'foo': True, 'bar': 42, 'baz': '!'} 

a = {'foo': d['foo'], 'bar': d['bar']} 
b = {'foo': d['foo'], 'baz': d['baz']} 
c = {'bar': d['bar'], 'baz': d['baz']} 

Sin duda, hay una mejor manera de expresar esto. De hecho, me leí los documentos con la esperanza de que el método de un diccionario copy acepta claves que deben incluirse en el nuevo diccionario:

# I'd hoped that something like this would work... 
a = d.copy('foo', 'bar') 
b = d.copy('foo', 'baz') 
c = d.copy('bar', 'baz') 

podría escribir una función para este propósito:

copydict = lambda dct, *keys: {key: dct[key] for key in keys} 

a = copydict(d, 'foo', 'bar') 
b = copydict(d, 'foo', 'baz') 
c = copydict(d, 'bar', 'baz') 

¿Hay una mejor solución que la anterior?

+0

¿Por qué no utiliza una lista (o un conjunto) para a, b, c? Mire en frío el valor en d cuando lo necesite. – maxy

+0

En realidad estoy pasando 'a',' b', y 'c' a la función' urlencode' de Django (que, como 'urllib.urlencode', acepta un diccionario). – davidchambers

+0

@BlaXpirit: debe escribir una respuesta que contenga solo "No." (rellene el tamaño mínimo con un comentario en HTML) para que todos podamos votarlo alocadamente. –

Respuesta

5

Supongo que la función en la pregunta es la mejor solución.

Por supuesto, alguien podría publicar algún código idiomático, pero estoy seguro de que no funcionaría mejor/más rápido. Iterar una lista y obtener elementos de una frase por clave es lo más rápido que puede obtener.

Una sugerencia es eliminar la estrella del parámetro keys. El desempaquetado de argumentos agrega una sobrecarga innecesaria. No debería haber problema con solo pasar esas teclas como una tupla.

0

como ha señalado @BlaXpirit, esta solución probablemente no va a ser mejor que la suya en términos de velocidad o facilidad de lectura, pero que podría ser algo como esto:

>>> from operator import itemgetter 
>>> d = {'foo': True, 'bar': 42, 'baz': '!'} 
>>> keys = ['foo', 'bar'] 
>>> dict(zip(keys, itemgetter(*keys)(d))) 
{'bar': 42, 'foo': True} 
3

La única mejora que hacer es utilizar una definición de función real, no un lambda:

def copy_dict(d, *keys): 
    """Make a copy of only the `keys` from dictionary `d`.""" 
    return {key: d[key] for key in keys} 

que podría ser útil para hacer frente a las teclas que faltan, pero en Python 2 no se pueden mezclar argumentos de palabra clave opcionales con args * muy bien, por lo que podría tiene que ir a un argumento de tupla:

def copy_dict(d, keys, default=None): 
    """Make a copy of only the `keys` from dictionary `d`. 

    Use `default` if a key is missing. 

    """ 
    return {key: d.get(key, default) for key in keys} 
Cuestiones relacionadas