Python 检查是否有两个人通过好友连接

Python 检查是否有两个人通过好友连接,python,python-3.x,Python,Python 3.x,每个子列表都表示他们是朋友,现在我想创建一个函数def is_connected_via_friendships_with,用于检查他们是否通过与其他人的友谊进行连接。例如,玛丽和卢卡斯是朋友。她和彼得是朋友,彼得和朱莉是朋友。因此,函数需要为Marie和Julie返回True。还请注意,我不能为此使用import。先谢谢你 network = {'friendships' :[['Marie', 'Lucas'], ['Lucas', 'Patsy'], ['Emma', 'Lucas'],

每个子列表都表示他们是朋友,现在我想创建一个函数
def is_connected_via_friendships_with
,用于检查他们是否通过与其他人的友谊进行连接。例如,玛丽和卢卡斯是朋友。她和彼得是朋友,彼得和朱莉是朋友。因此,函数需要为Marie和Julie返回
True
。还请注意,我不能为此使用
import
。先谢谢你

network = {'friendships' :[['Marie', 'Lucas'], ['Lucas', 'Patsy'], ['Emma', 'Lucas'], ['Emma', 'Kevin'], ['Peter', 'Emma'], ['Peter', 'Lucas'], ['Peter', 'Julie'], ['Suzy', 'Tobias']]}
print (is_connected_via_friendships_with(network, 'Marie', 'Julie')) # true
print (is_connected_via_friendships_with(network, 'Julie', 'Tobias')) # false
print (is_connected_via_friendships_with(network, 'Julie', 'Frank'))  # false

基本上,你必须找出两个朋友是否位于图中相同的连通部分。检查两个节点是否位于同一连接组件中的多种方法。您可以使用不相交集来优化此问题的实现。从中使用的不相交集实现

守则如下:

class DisjointSet:
    def __init__(self, vertices, parent):
        self.vertices = vertices
        self.parent = parent

    def find(self, item):
        if self.parent[item] == item:
            return item
        else:
            return self.find(self.parent[item])

    def union(self, set1, set2):
        root1 = self.find(set1)
        root2 = self.find(set2)
        self.parent[root1] = root2

    def is_in_same_set(self, fa, fb):
        return self.find(fb) == self.find(fa)

def get_vertices(network):
    myset = set()
    for a,b in network['friendships']:
        myset.add(a)
        myset.add(b)
    return list(myset)


def is_connected_via_friendships_with(network, fa,fb):
    return network.is_in_same_set(fa,fb)

def main():

    network = {'friendships' :[['Marie', 'Lucas'], ['Lucas', 'Patsy'], ['Emma','Lucas'], ['Emma', 'Kevin'], ['Peter', 'Emma'], ['Peter', 'Lucas'], ['Peter', 'Julie'],     ['Suzy', 'Tobias']]}

    vertices = get_vertices(network)
    parent = {}

    for v in vertices:
        parent[v] = v

    ds = DisjointSet(vertices, parent)

    for a,b in network['friendships']:
        ds.union(a,b)

    print(is_connected_via_friendships_with(ds, 'Marie', 'Julie'))
    print(is_connected_via_friendships_with(ds, 'Peter', 'Suzy'))
main()
输出为:

正确
假的


基本上,你必须找出两个朋友是否位于图中相同的连通部分。检查两个节点是否位于同一连接组件中的多种方法。您可以使用不相交集来优化此问题的实现。从中使用的不相交集实现

守则如下:

class DisjointSet:
    def __init__(self, vertices, parent):
        self.vertices = vertices
        self.parent = parent

    def find(self, item):
        if self.parent[item] == item:
            return item
        else:
            return self.find(self.parent[item])

    def union(self, set1, set2):
        root1 = self.find(set1)
        root2 = self.find(set2)
        self.parent[root1] = root2

    def is_in_same_set(self, fa, fb):
        return self.find(fb) == self.find(fa)

def get_vertices(network):
    myset = set()
    for a,b in network['friendships']:
        myset.add(a)
        myset.add(b)
    return list(myset)


def is_connected_via_friendships_with(network, fa,fb):
    return network.is_in_same_set(fa,fb)

def main():

    network = {'friendships' :[['Marie', 'Lucas'], ['Lucas', 'Patsy'], ['Emma','Lucas'], ['Emma', 'Kevin'], ['Peter', 'Emma'], ['Peter', 'Lucas'], ['Peter', 'Julie'],     ['Suzy', 'Tobias']]}

    vertices = get_vertices(network)
    parent = {}

    for v in vertices:
        parent[v] = v

    ds = DisjointSet(vertices, parent)

    for a,b in network['friendships']:
        ds.union(a,b)

    print(is_connected_via_friendships_with(ds, 'Marie', 'Julie'))
    print(is_connected_via_friendships_with(ds, 'Peter', 'Suzy'))
main()
输出为:

正确
假的

这是一个经典问题。既然友谊是双向的,将子列表列表转换为一组可散列的冻结集作为候选池更为有效,这样,对于每个起始顶点,您可以通过迭代冻结集集中的候选点来找到连接的组件,以找到与当前组件集相交的冻结集,并将其从候选池中移除,在人才库中不再有候选人之前:

pool = set(map(frozenset, network['friendships']))
groups = []
while pool:
    groups.append(set(pool.pop()))
    while True:
        for candidate in pool:
            if groups[-1] & candidate:
                groups[-1] |= candidate
                pool.remove(candidate)
                break
        else:
            break
组将成为:

[{'Patsy', 'Emma', 'Peter', 'Marie', 'Julie', 'Kevin', 'Lucas'}, {'Suzy', 'Tobias'}]
然后,将集合列表转换为集合的dict,并将每个名称作为有效查找的关键,这很简单:

connected = {name: group for group in groups for name in group}
def is_connected_via_friendships_with(name1, name2):
    return name2 in connected.get(name1, ())
以便:

print(is_connected_via_friendships_with('Marie', 'Julie'))
print(is_connected_via_friendships_with('Julie', 'Tobias'))
print(is_connected_via_friendships_with('Julie', 'Frank'))
产出:

True
False
False
这是一个经典问题。既然友谊是双向的,将子列表列表转换为一组可散列的冻结集作为候选池更为有效,这样,对于每个起始顶点,您可以通过迭代冻结集集中的候选点来找到连接的组件,以找到与当前组件集相交的冻结集,并将其从候选池中移除,在人才库中不再有候选人之前:

pool = set(map(frozenset, network['friendships']))
groups = []
while pool:
    groups.append(set(pool.pop()))
    while True:
        for candidate in pool:
            if groups[-1] & candidate:
                groups[-1] |= candidate
                pool.remove(candidate)
                break
        else:
            break
组将成为:

[{'Patsy', 'Emma', 'Peter', 'Marie', 'Julie', 'Kevin', 'Lucas'}, {'Suzy', 'Tobias'}]
然后,将集合列表转换为集合的dict,并将每个名称作为有效查找的关键,这很简单:

connected = {name: group for group in groups for name in group}
def is_connected_via_friendships_with(name1, name2):
    return name2 in connected.get(name1, ())
以便:

print(is_connected_via_friendships_with('Marie', 'Julie'))
print(is_connected_via_friendships_with('Julie', 'Tobias'))
print(is_connected_via_friendships_with('Julie', 'Frank'))
产出:

True
False
False

你都试了些什么?您可能需要考虑添加您尝试过的代码!问题是它是更大代码的一部分,并且使用其他函数。如果他们有共同的朋友,我知道怎么做,但我真的找不到一个合适的方法来解决这个问题。你可以使用多种方法来解决这个问题,我添加了一个不相交集解决方案!你都试了些什么?您可能需要考虑添加您尝试过的代码!问题是它是更大代码的一部分,并且使用其他函数。如果他们有共同的朋友,我知道怎么做,但我真的找不到一个合适的方法来解决这个问题。你可以使用多种方法来解决这个问题,我添加了一个不相交集解决方案!如何在不使用
break
的情况下编写此代码?他们说这是不好的实践,我不能使用它。不确定“他们”是谁,但是
break
是一个使代码干净高效的好工具。这从来都不是一个坏习惯。如果你不使用它,你将不得不使用一个布尔标志来表示何时结束循环,这使得代码更加混乱。我的大学是这么说的。很愚蠢,我不能使用它,因为我已经读了很多关于它如何非常有用的书。你如何在不使用
break
的情况下编写它?他们说这是不好的实践,我不能使用它。不确定“他们”是谁,但是
break
是一个使代码干净高效的好工具。这从来都不是一个坏习惯。如果你不使用它,你将不得不使用一个布尔标志来表示何时结束循环,这使得代码更加混乱。我的大学是这么说的。我不能用它是愚蠢的,因为我读了很多关于它是如何非常有用的