Tenho uma lista com um número variável de dicionários, por exemplo:
var = [ {'a': 1, 'b': 2}, {'b': 20, 'a': 10, 'c': 30}, {'c': 300, 'a': 100} ]
Preciso extrair as chaves que são comuns a todos os dictos, fazer uma lista de seus valores associados, criar um novo dict a partir dele e armazená-lo na mesma variável:
O resultado esperado seria:
var = { 'a': [1, 10, 100] }
Posso encontrar a interseção das chaves com:
[k for k in var[0] if all(k in d for d in var[1:])]
Mas como você pode fazer o resto da transformação?
Depois de ter as chaves comuns, você pode usar uma compreensão de ditado e definir o valor como uma compreensão de lista aninhada:
Observação:
Para encontrar as chaves comuns você pode transformar os dictos em conjuntos (isso fará um conjunto usando apenas as chaves) e então usar a interseção de conjuntos:
Depois de conhecer as chaves de seu interesse, apenas itere e puxe-as conforme você avança:
Uma linha única também é possível (já que você garantiu que as chaves existem em todos
dict
os s), é um pouco feio, considerando a quantidade de significado que ela coloca em uma única linha:Nesse caso, o one-liner está bom, mas é um pouco menos flexível se você precisar modificá-lo; o loop explícito é mais fácil de ajustar, porém mais detalhado.
Nota lateral: existe uma maneira mais simples/rápida de calcular as chaves comuns:
Isso converte as chaves do primeiro
dict
em aset
e permite queset
ointersection
método produza a interseção em uma única chamada na camada C (não é significativamente diferente na forma como opera em relação ao seu código, mas evita uma tonelada de sobrecarga do intérprete) .Você pode até fazer com que ele lide silenciosamente com um vazio
var
, alterando-o para:que produzirá um vazio
set
forcommon_keys
ifvar
contains nodict
s (a escolha depende do cenário; se esvaziarvar
for um erro, morrer ruidosamente é melhor do que fazer um trabalho inválido silenciosamente).Combinar as duas partes permitiria que você alcançasse a solução verdadeiramente horrível como um all-in-one-liner completo:
mas esse é um código realmente horrível, então sugiro dividi-lo um pouco.