Digamos que eu tenho uma lista de dicionários:
[
{'id': 1, 'name': 'john', 'age': 34},
{'id': 1, 'name': 'john', 'age': 34},
{'id': 2, 'name': 'hanna', 'age': 30},
]
e preciso obter uma lista de dicionários exclusivos (removendo as duplicatas):
[
{'id': 1, 'name': 'john', 'age': 34},
{'id': 2, 'name': 'hanna', 'age': 30},
]
Alguém pode me ajudar com a maneira mais eficiente de conseguir isso em Python?
python
dictionary
Limaaf
fonte
fonte
set(frozenset(i.items()) for i in list)
Respostas:
Então faça um ditado temporário com a chave sendo
id
. Isso filtra as duplicatas. Ovalues()
ditado será a listaEm Python2.7
Em Python3
Em Python2.5 / 2.6
fonte
{str(v['flight'])+':'+str(v['lon'])+','+str(v['lat']): v for v in stream}.values()
Isso cria uma chave exclusiva com base em seus valores. Como'MH370:-21.474370,86.325589'
{(v['flight'], v['lon'], v['lat']): v for v in stream}.values()
OrderedDict
a partircollections
list(OrderedDict((v['id'], v) for v in L).values())
ou classificar a lista resultante se isso funciona melhor para vocêlist({str(i):i for i in L}.values())
Aqui, usamos str (i) para criar uma string exclusiva que representa o dicionário que é usado para filtrar as duplicatas.A maneira usual de encontrar apenas os elementos comuns em um conjunto é usar a
set
classe do Python . Basta adicionar todos os elementos ao conjunto, depois converter o conjunto para alist
e, uma vez que as duplicatas desapareceram.O problema, é claro, é que a
set()
pode conter apenas entradas laváveis e adict
não é lavável.Se eu tivesse esse problema, minha solução seria converter cada
dict
uma em uma string que represente odict
, adicione todas as strings a eset()
depois leia os valores da string comolist()
ae converta novamente emdict
.Uma boa representação de um
dict
formato de sequência é o formato JSON. E o Python possui um módulo interno para JSON (chamado, éjson
claro).O problema restante é que os elementos em a
dict
não são ordenados e, quando o Python converte adict
string em JSON, você pode obter duas strings JSON que representam dicionários equivalentes, mas não são strings idênticas. A solução fácil é passar o argumentosort_keys=True
quando você ligarjson.dumps()
.EDIT: Esta solução estava assumindo que um dado
dict
poderia ter qualquer parte diferente. Se pudermos assumir que todosdict
com o mesmo"id"
valor corresponderão ao outrodict
com o mesmo"id"
valor, isso será um exagero; A solução do @ gnibbler seria mais rápida e fácil.EDIT: Agora, há um comentário de André Lima dizendo explicitamente que, se o ID for uma duplicata, é seguro assumir que o todo
dict
é uma duplicata. Portanto, essa resposta é um exagero e eu recomendo a resposta do @ gnibbler.fonte
Caso os dicionários sejam identificados exclusivamente por todos os itens (o ID não está disponível), você poderá usar a resposta usando JSON. A seguir, é uma alternativa que não usa JSON e funcionará desde que todos os valores do dicionário sejam imutáveis
fonte
Você pode usar a biblioteca numpy (funciona apenas para Python2.x):
Para que ele funcione com o Python 3.x (e versões recentes do numpy), você precisa converter uma matriz de dicts em uma matriz numpy de seqüências de caracteres, por exemplo
fonte
TypeError: unorderable types: dict() > dict()
ao fazer isso no Python 3.5.Aqui está uma solução razoavelmente compacta, embora eu suspeito que não seja particularmente eficiente (para dizer o mínimo):
fonte
map()
chamadalist()
no Python 3 para recuperar uma lista, caso contrário, é ummap
objeto.Como o
id
é suficiente para detectar duplicatas e oid
é lavável: execute-o através de um dicionário que tenhaid
como chave. O valor para cada chave é o dicionário original.No Python 3,
values()
não retorna uma lista; você precisará envolver todo o lado direito dessa expressãolist()
e escrever a carne da expressão mais economicamente como uma compreensão de ditado:Observe que o resultado provavelmente não estará na mesma ordem que o original. Se isso é um requisito, você pode usar a em
Collections.OrderedDict
vez de adict
.Como um aparte, pode fazer bastante sentido manter apenas os dados em um dicionário que use a
id
chave como para começar.fonte
saídas:
fonte
Expandindo a resposta de John La Rooy ( Python - Lista de dicionários únicos ), tornando-a um pouco mais flexível:
Função de chamada:
fonte
Nós podemos fazer com
pandas
Observe um pouco diferente da resposta de aceitação.
drop_duplicates
irá verificar todas as colunas nos pandas, se todas forem iguais, a linha será descartada.Por exemplo :
Se mudarmos o segundo
dict
nome de john para peterfonte
No python 3.6+ (o que eu testei), basta usar:
Explicação: estamos mapeando
json.dumps
para codificar os dicionários como objetos json, que são imutáveis.set
pode então ser usado para produzir um iterável de imutáveis exclusivos . Finalmente, convertemos de volta para a nossa representação de dicionário usandojson.loads
. Observe que, inicialmente, é preciso classificar por chaves para organizar os dicionários de uma forma única. Isso é válido para o Python 3.6+, pois os dicionários são ordenados por padrão.fonte
list
antes de fazerset
.Resumi meus favoritos para experimentar:
https://repl.it/@SmaMa/Python-List-of-unique-dictionaries
fonte
Uma solução rápida e suja é apenas gerar uma nova lista.
fonte
Não sei se você deseja apenas que o id de seus dictos na lista seja exclusivo, mas se o objetivo é ter um conjunto de dictos em que a unicidade esteja nos valores de todas as chaves. em sua compreensão:
Espero que ajude você ou outra pessoa que tenha a preocupação ....
fonte
Há muitas respostas aqui, então deixe-me adicionar outra:
fonte
Opção bastante simples:
fonte
Bem, todas as respostas mencionadas aqui são boas, mas em algumas respostas pode-se enfrentar um erro se os itens do dicionário tiverem lista ou dicionário aninhado, então proponho uma resposta simples
fonte
Heres uma implementação com pouca sobrecarga de memória ao custo de não ser tão compacta quanto o resto.
resultado:
fonte
index
atlen(values)
e contando para trás, o que significa que você sempre pode diminuirindex
se você estádel
ou não. por exemplofor index in reversed(range(len(values))):
Esta é a solução que encontrei:
Basicamente, você verifica se o ID está presente na lista; se estiver, exclua o dicionário; caso contrário, anexe o ID à lista.
fonte