Есть ли элегантный способ отслеживать наборы связанных элементов в Python?

1

Для определенной части кода мне нужно было найти способ распознать определенные псевдонимы. Дело в том, что заранее не известно, что эти псевдонимы.

Это мои требования:

  • Если A и B - псевдонимы, а B и C - псевдонимы, A и C также должны быть алиасами.
  • Два набора псевдонимов должны быть объединены, когда они связаны каким-либо образом.
  • В каждом наборе псевдонимов должен быть первичный псевдоним.

Я использую следующее решение, используя то, что сводится к словарю множеств:

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

Можно ли улучшить это? Например, используя класс в стандартной библиотеке (я искал, но, возможно, я пропустил что-то полезное.)

Теги:

2 ответа

2
Лучший ответ

Это то, что вы можете отобразить на графике, чтобы я сделал:

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']]

Вы не укажете, какой псевдоним должен быть основным, поэтому вы также можете выбрать первый из этих списков.

networkx модуль

3

Рассматривали ли вы использование disjoint set? Практически O(1) скорость, легко реализуется и, по-видимому, точно соответствует вашим требованиям.

  • 0
    Это выглядит интересно, но на самом деле это выглядит как шаг назад от того, что я имею сейчас. Хотя не уверен насчет этого.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню