Обновление
Исходя из комментариев и правок к вопросу, исходный ответ был неверным, поскольку он учитывался только при наличии подходящей пары для данного отношения вместо того, чтобы требовать всех элементов для этого отношения, чтобы иметь совпадающую пару. Эта функция решает эту проблему:
def symmetric_relationships(A):
A = set(tuple(e) for e in A)
rels = set(r for (_, r, _) in A)
return [r for r in rels if all((i2, rel, i1) in A for (i1, rel, i2) in A if rel == r)]
Например:
A = [
["item1", "relationstype1", "item2"],
["item3", "relationstype2", "item2"],
["item2", "relationstype1", "item1"]
]
print(symmetric_relationships(A))
A.append(["item3", "relationstype1", "item1"])
print(symmetric_relationships(A))
A.append(["item2", "relationstype2", "item3"])
print(symmetric_relationships(A))
A.append(["item1", "relationstype1", "item3"])
print(symmetric_relationships(A))
Выход:
['relationstype1']
[]
['relationstype2']
['relationstype1', 'relationstype2']
Оригинальный ответ
Вы можете грубо форсировать это с помощью понимания списка:
r = [r for i1, r, i2 in A if [i2, r, i1] in A]
это даст
['relationstype1', 'relationstype1']
, который можно преобразовать в список с уникальным значением с помощью
list(set(r))
Если item1
никогда не совпадает с item2
, вы также можете пропустить последний шаг, добавив i1 < i2
тест к списку:
r = [r for i1, r, i2 in A if [i2, r, i1] in A and i1 < i2]
По производительности вы, вероятно, можете улучшить его, преобразовав A
в набор (после первого преобразования в кортежи):
A = set(tuple (e) for e in A)
r = [r for i1, r, i2 in A if (i2, r, i1) in A and i1 < i2]