Для определенной части кода мне нужно было найти способ распознать определенные псевдонимы. Дело в том, что заранее не известно, что эти псевдонимы.
Это мои требования:
Я использую следующее решение, используя то, что сводится к словарю множеств:
class Alias(object):
def __init__(self, initial):
self._set = {initial}
self.initial = initial
def add(self, alias):
self._set.add(alias)
def merge(self, other):
self._set.update(other._set)
def __iter__(self):
return iter(self._set)
class AliasDict(object):
def __init__(self):
self._dict = {}
def add(self, one, other):
if one in self._dict:
if other in self._dict: #merge!
self._dict[one].merge(self._dict[other])
for k in self._dict[other]:
self._dict[k] = self._dict[one]
else:
self._dict[one].add(other)
elif other in self._dict:
self._dict[other].add(one)
else:
self._dict[one] = self._dict[other] = Alias(one)
self._dict[one].add(other)
def get(self, n):
return self._dict.get(n)
def __contains__(self, s):
return s in self._dict
Можно ли улучшить это? Например, используя класс в стандартной библиотеке (я искал, но, возможно, я пропустил что-то полезное.)
Это то, что вы можете отобразить на графике, чтобы я сделал:
from networkx import Graph
from networkx.algorithms.components.connected import connected_components
# see aliases as the edges between nodes in a graph
aliases = [('A', 'B'), ('B', 'C'), ('D','E')]
g = Graph( aliases )
# connected components are alias groups
print connected_components(g) # [['A', 'C', 'B'], ['E', 'D']]
Вы не укажете, какой псевдоним должен быть основным, поэтому вы также можете выбрать первый из этих списков.
Рассматривали ли вы использование disjoint set? Практически O(1)
скорость, легко реализуется и, по-видимому, точно соответствует вашим требованиям.