Estou fazendo essa coisa de mesa telefônica em python em que preciso manter o controle de quem está falando com quem, então se Alice -> Bob, isso implica que Bob -> Alice.
Sim, eu poderia preencher dois mapas hash, mas estou me perguntando se alguém tem uma ideia de fazer isso com um.
Ou sugira outra estrutura de dados.
Não existem várias conversas. Digamos que isso seja para um call center de atendimento ao cliente, então, quando Alice discar para a mesa telefônica, ela falará apenas com Bob. Suas respostas também vão apenas para ela.
Respostas:
Você pode criar seu próprio tipo de dicionário criando uma subclasse
dict
e adicionando a lógica que deseja. Aqui está um exemplo básico:E funciona assim:
Tenho certeza de que não cobri todos os casos, mas isso deve ajudar você a começar.
fonte
.add
método para fazer coisas como, emd.add('Bob', 'Alice')
vez de usar a sintaxe que mostrei. Eu também incluiria algum tratamento de erros. Mas você entendeu a ideia básica. :)d['foo'] = 'baz'
seria necessário remover abar
chave adicionalmente ).dict
produz algum comportamento enganoso aqui, pois se você criar o objeto com algum conteúdo inicial, a estrutura será quebrada.__init__
precisa ser substituído para permitir que uma construçãod = TwoWayDict({'foo' : 'bar'})
funcione corretamente.pip install bidict
. URL: pypi.python.org/pypi/bidictNo seu caso especial, você pode armazenar ambos em um dicionário:
Já que o que você está descrevendo é uma relação simétrica.
A -> B => B -> A
fonte
Eu sei que é uma pergunta mais antiga, mas gostaria de mencionar outra ótima solução para esse problema, ou seja, o bidict do pacote python . É extremamente simples de usar:
fonte
Eu apenas preencheria um segundo hash, com
fonte
reverse_map = dict(reversed(item) for item in forward_map.items())
my_dict.update(dict(reversed(item) for item in my_dict.items()))
Unexpected type(s): (Generator[Iterator[Union[str, Any]], Any, None]) Possible types: (Mapping) (Iterable[Tuple[Any, Any]])
. Alguma ideia de como se livrar do aviso?Dois mapas de hash são provavelmente a solução de desempenho mais rápido, supondo que você possa poupar memória. Eu os envolveria em uma única classe - a responsabilidade do programador é garantir que dois mapas de hash sejam sincronizados corretamente.
fonte
mydict[:value]
para obterkey
(ao custo de algum desempenho)Você tem dois problemas separados.
Você tem um objeto "Conversa". Refere-se a duas Pessoas. Como uma pessoa pode ter várias conversas, você tem um relacionamento de muitos para muitos.
Você tem um mapa de pessoa para uma lista de conversas. Uma conversão terá um par de pessoas.
Faça algo assim
fonte
Não, realmente não há como fazer isso sem criar dois dicionários. Como seria possível implementar isso com apenas um dicionário e, ao mesmo tempo, oferecer desempenho comparável?
É melhor criar um tipo personalizado que encapsule dois dicionários e exponha a funcionalidade desejada.
fonte
Uma forma menos prolixa, ainda usando o reverso:
fonte
Você pode usar um
DoubleDict
conforme mostrado na receita 578224 do Python Cookbook .fonte
Outra solução possível é implementar uma subclasse de
dict
, que contém o dicionário original e mantém o controle de uma versão reversa dele. Manter dois dictes separados pode ser útil se as chaves e os valores estiverem sobrepostos.Exemplo:
fonte
Existe a biblioteca de coleções estendidas em pypi: https://pypi.python.org/pypi/collections-extended/0.6.0
Usar a classe bijection é tão fácil quanto:
fonte
Gostei da sugestão do bidict em um dos comentários.
pip install bidict
Uso:
Já que não há muitos documentos sobre isso. Mas tenho todos os recursos de que preciso funcionando corretamente.
Impressões:
fonte
O módulo de extensão kjbuckets C fornece uma estrutura de dados em "gráfico" que acredito dar a você o que você deseja.
fonte
Aqui está mais uma implementação de dicionário bidirecional, estendendo a
dict
classe pythons , caso você não goste de nenhuma das outras:Use-o como um dicionário python normal, exceto na construção:
fonte
Uma maneira que gosto de fazer esse tipo de coisa é algo como:
fonte