Python verifica se existe uma lista de chaves no dicionário

87

Eu tenho um dicionário parecido com este:

grades = {
        'alex' : 11,
        'bob'  : 10,
        'john' : 14,
        'peter': 7
       }

e uma lista de nomes students = ('alex', 'john')

Preciso verificar se todos os nomes studentsexistem como chaves em gradesdict.

gradespode ter mais nomes, mas todos os nomes em studentsdevem estar emgrades

Deve haver uma maneira direta de fazer isso, mas ainda sou novo no python e não consigo descobrir. tentei if students in grades, não funcionou.

Nos casos reais, as listas serão muito maiores.

applechief
fonte

Respostas:

195

Use all():

if all(name in grades for name in students):
    # whatever
Sven Marnach
fonte
Ótimo! Existe alguma forma de atalho para obter os elementos que estão faltando no dic se a condição for False?
guival
2
@guival Sim, você pode usar operações de definição, por exemplo, set(students) - grades.keys()em Python 3.
Sven Marnach
há uma maneira de verificar se alguma de uma lista de chaves é uma string secundária em uma string?
Jonathan,
@Jonathan Não tem certeza do que você quer dizer, talvez any(k in my_string for k in keys)?
Sven Marnach
@SvenMarnach acabou de descobrir qualquer ()! Isso é exatamente o que eu estava procurando :)
Jonathan
22
>>> grades = {
        'alex' : 11,
        'bob'  : 10,
        'john' : 14,
        'peter': 7
}
>>> names = ('alex', 'john')
>>> set(names).issubset(grades)
True
>>> names = ('ben', 'tom')
>>> set(names).issubset(grades)
False

Chamar classé inválido, então mudei para names.

Jamylak
fonte
Isso não pode ser um atalho, ao contrário all(). Será sempre O (m + n), onde m e n são os respectivos tamanhos de namese grades. O uso all()será O (m) e pode ser um atalho.
Sven Marnach
7
@SvenMarnach Certo, vou deixar aqui, pois é outra abordagem, mas concordo que a sua é a melhor.
Jamylak
Definitivamente, deixe aqui! Em qualquer caso, é uma abordagem interessante.
Sven Marnach de
3

Assumindo alunos conforme definido

if not (students - grades.keys()):
    print("All keys exist")

Se não, converta em conjunto

if not (set(students) - grades.keys()):
    print("All keys exist")
abhilekh
fonte
0

Você pode testar se várias chaves estão em um dicionário aproveitando que <dict>.keys()retorna a set.

Esta lógica no código ...

if 'foo' in d and 'bar' in d and 'baz' in d:
    do_something()

pode ser representado mais resumidamente como:

if {'foo', 'bar', 'baz'} <= d.keys():
    do_something()

O <=operador para conjuntos testa se o conjunto à esquerda é um subconjunto do conjunto à direita. Outra maneira de escrever isso seria <set>.issubset(other).

Existem outras operações interessantes suportadas por conjuntos: https://docs.python.org/3.8/library/stdtypes.html#set

Usar esse truque pode condensar muitos lugares no código que verificam várias chaves, conforme mostrado no primeiro exemplo acima.

Listas inteiras de chaves também podem ser verificadas usando <=:

if set(students) <= grades.keys():
    print("All studends listed have grades in your class.")

# or using unpacking - which is actually faster than using set()
if {*students} <= grades.keys():
    ...

Ou se studentstambém é um ditado:

if students.keys() <= grades.keys():
    ...
Todd
fonte