Compreensão Do Dicionário Python

é possível criar uma compreensão de dicionário em Python (para as chaves)?

sem as compreensões de listas, você pode usar algo assim:

l = []
for n in range(1, 11):
    l.append(n)
Podemos encurtar isto para uma compreensão de Lista: l = [n for n in range(1, 11)].

No entanto, digamos que quero definir as chaves de um dicionário para o mesmo valor. Eu posso fazer:

d = {}
for n in range(1, 11):
     d[n] = True # same value for each
Já tentei isto.
d = {}
d[i for i in range(1, 11)] = True
No entanto, tenho um SyntaxError No for.

além disso (eu não preciso desta parte, mas apenas querendo saber), pode você define as chaves de um dicionário para um monte de valores diferentes, como este:

d = {}
for n in range(1, 11):
    d[n] = n
Isto é possível com uma compreensão de dicionário?

d = {}
d[i for i in range(1, 11)] = [x for x in range(1, 11)]
Isto também levanta um SyntaxError No for.

Author: Kevin Guan, 2013-01-24

8 answers

Existem compreensões de dicionário em Python 2.7+, mas elas não funcionam como você está tentando. Como uma compreensão de Lista, eles criam um dicionário novo ; Você não pode usá-los para adicionar chaves a um dicionário existente. Além disso, você tem que especificar as chaves e os valores, Embora é claro que você pode especificar um valor fictício, se quiser.

>>> d = {n: n**2 for n in range(5)}
>>> print d
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Se quiser que todos sejam verdadeiros:

>>> d = {n: True for n in range(5)}
>>> print d
{0: True, 1: True, 2: True, 3: True, 4: True}
O que parece estar a pedir é uma forma de definir várias teclas em uma vez num dicionário existente. Não há atalho directo para isso. Você pode fazer um loop como você já mostrou, ou você pode usar uma compreensão de dicionário para criar um novo dict com os novos valores, e então fazer oldDict.update(newDict) para juntar os novos valores no dict antigo.
 435
Author: BrenBarn, 2017-02-09 03:59:36

Pode usar o método da classe dict.fromkeys...

>>> dict.fromkeys(range(1, 11), True)
{1: True, 2: True, 3: True, 4: True, 5: True, 6: True, 7: True, 8: True, 9: True, 10: True}

Esta é a maneira mais rápida de criar um dicionário onde todas as chaves mapeiam para o mesmo valor.

Tenha cuidado ao usar isto com objectos mutáveis.

d = dict.fromkeys(range(10), [])
d[1].append(2)
print(d[2])  # ???

Se você não precisa realmente de para inicializar todas as chaves, a defaultdict pode ser útil também:

from collections import defaultdict
d = defaultdict(lambda: True)

Para responder à segunda parte, uma compreensão dict é exatamente o que você precisa:

{k: k for k in range(10)}

Ou para python2. 6:

dict((k, k) for k in range(10))

Você também pode criar uma subclasse inteligente de dict que funciona um pouco como um defaultdict Se você sobrepor __missing__:

>>> class KeyDict(dict):
...    def __missing__(self, key):
...       #self[key] = key  # Maybe add this also??? 
...       return key
... 
>>> d = KeyDict()
>>> d[1]
1
>>> d[2]
2
>>> d[3]
3
>>> print(d)
{}
Puro.
 141
Author: mgilson, 2014-08-28 14:44:04
>>> {i:i for i in range(1, 11)}
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10}
 23
Author: NPE, 2013-01-24 17:55:37

Eu realmente gosto do comentário @mgilson, uma vez que se você tem dois iterables, um que corresponde às chaves e o outro os valores, Você também pode fazer o seguinte.

keys = ['a', 'b', 'c']
values = [1, 2, 3]
d = dict(zip(keys, values))

Dar

D = {'a': 1, 'b': 2, 'c': 3}

 19
Author: ehontz, 2014-08-16 18:03:34

Use dict () numa lista de tuplas, esta solução permitir-lhe-á ter valores arbitrários em cada lista, desde que sejam do mesmo comprimento

i_s = range(1, 11)
x_s = range(1, 11)
# x_s = range(11, 1, -1) # Also works
d = dict([(i_s[index], x_s[index], ) for index in range(len(i_s))])
 11
Author: Bryan, 2013-01-24 17:55:26

Considere este exemplo de contar a ocorrência de palavras numa lista usando a compreensão do dicionário

my_list = ['hello', 'hi', 'hello', 'today', 'morning', 'again', 'hello']
my_dict = {k:my_list.count(k) for k in my_list}
print(my_dict)

E o resultado é

{'again': 1, 'hi': 1, 'hello': 3, 'today': 1, 'morning': 1}
 10
Author: adonese, 2016-02-17 19:51:40

O principal objectivo de uma compreensão da lista é criar uma nova lista baseada noutra sem alterar ou destruir a lista original.

Em vez de escrever

    l = []
    for n in range(1, 11):
        l.append(n)

Ou

    l = [n for n in range(1, 11)]

Você deve escrever apenas

    l = range(1, 11)
Nos dois blocos de código de topo, estás a criar uma nova lista, a passar por ela e a devolver cada elemento. É apenas uma forma Cara de criar uma cópia da lista.

Para obter um novo dicionário com todas as chaves ajustadas para o mesmo valor com base em outro dict, faça isso:

    old_dict = {'a': 1, 'c': 3, 'b': 2}
    new_dict = { key:'your value here' for key in old_dict.keys()}
Estás a receber um SyntaxError porque quando escreves
    d = {}
    d[i for i in range(1, 11)] = True

Você está basicamente dizendo:" Defina minha chave 'I para i no intervalo(1, 11)' Para verdadeiro "e" i para i no intervalo(1, 11) " não é uma chave válida, é apenas um erro de sintaxe. Se os dicts suportarem listas como teclas, você faria algo como

    d[[i for i in range(1, 11)]] = True

E não

    d[i for i in range(1, 11)] = True

Mas as listas não são hashable, então você não pode usá-las como chaves dict.

 7
Author: Bonifacio2, 2013-01-24 18:53:48
Não podes usar uma lista dessas. tente isso em vez disso, ele usa tuplas
d[tuple([i for i in range(1,11)])] = True
 -3
Author: Aditya Sihag, 2013-01-24 17:58:12