способ вернуть подмножество списка элементов с некоторыми предопределенными свойствами? - PullRequest
0 голосов
/ 10 апреля 2020

У меня есть список A с элементами, представляющими отношения вида ["item1", "relationstype" ,"item2"].

Я хочу написать функцию, которая возвращает список всех типов отношений, такой, что если ["item1", "relationstype" ,"item2"] находится в A, то ["item2", "relationstype" ,"item1"] также находится в A.

Например, если A=[["item1", "relationstype1" ,"item2"],["item3", "relationstype2" ,"item2"],["item2", "relationstype1" ,"item1"],["item2", "relationstype2" ,"item3"],["item3", "relationstype2" ,"item4"]], тогда метод должен вернуть ["relationstype1"].

Вот что я пытался:

def find_symmetric_realations(A):
    relation_dict = {}
    symmetric_realations = set()
    for elem in A:
        relationstype = elem[1]
        if relationstype not in relation_dict:
            relation_dict[relationstype] = [(elem[0], elem[2])] # pout relation in dic
        else:
            if (elem[2],elem[0]) in relation_dict[relationstype]:
                continue
            else:
                relation_dict[relationstype].append((elem[0], elem[2]))
    # print(relation_dict[list(relation_dict.keys())[0]])
    for elem in relation_dict:
        if all((b,a) in relation_dict[elem] for (a,b) in relation_dict[elem]):
            symmetric_realations.add(elem)
    return list(symmetric_realations)

Ответы [ 3 ]

3 голосов
/ 10 апреля 2020

Обновление

Исходя из комментариев и правок к вопросу, исходный ответ был неверным, поскольку он учитывался только при наличии подходящей пары для данного отношения вместо того, чтобы требовать всех элементов для этого отношения, чтобы иметь совпадающую пару. Эта функция решает эту проблему:

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]
1 голос
/ 10 апреля 2020

Следующая функция находит симметричные c отношения в вашем списке:

def find_symmetric_realations(A):
    relation_dict = {}
    symmetric_realations = set()

    for elem in A:
        relationstype = elem[1]
        if relationstype not in relation_dict:
            relation_dict[relationstype] = [(elem[0], elem[2])]
        else:
            if (elem[2],elem[0]) in relation_dict[relationstype]:
                symmetric_realations.add(relationstype)
            else:
                relation_dict[relationstype].append((elem[0], elem[2]))

    return symmetric_realations
0 голосов
/ 10 апреля 2020
for index,list1 in enumerate(A):
    for list2 in A[index:]:
        check =  all(item in list1 for item in list2)
        if check==True and list1!=list2:
            print(list1[1])

Объяснение: При циклическом перечислении (A) мы получаем индексы и отдельные списки. 'check' сохраняет True, если все элементы list1 находятся в list2 (из 2nd l oop). Если check == true, но list1 не равен list2, выведите среднее значение, т.е. отношение

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...