方法返回具有某些预定义属性的元素列表的子集?

2024-06-12 12:55:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个列表A,其中的元素表示形式为["item1", "relationstype" ,"item2"]的关系

我想写一个函数,返回所有“relationstype”的列表,如果["item1", "relationstype" ,"item2"]在a中,那么["item2", "relationstype" ,"item1"]也在a中

对于rexample,如果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)

Tags: in列表forifdictrelationitem1symmetric
3条回答
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)上循环,我们得到索引&;单一列表。”如果列表1的所有元素都在列表2中(来自第二个循环),则选中“存储为真”。如果check==true,但list1不等于list2,则打印中间值,即关系

以下函数用于在列表中查找对称关系:

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

更新

根据对问题的评论和编辑,原始答案是不正确的,因为它只考虑了给定关系是否存在匹配对,而不是要求该关系的所有元素都有匹配对。此函数解决了该问题:

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))

如果item1item2不完全相同,也可以通过向列表添加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]

相关问题 更多 >