简体   繁体   English

在python中创建认识其他朋友的朋友字典

[英]Creating dictionaries of Friends that know other Friends in python

In any group of people there are many pairs of friends. 在任何一群人中都有很多对朋友。 Assume that two people who share a friend are friends themselves. 假设共享一个朋友的两个人本身就是朋友。 (Yes, this is an unrealistic assumption in real life, but let's make it nevertheless). (是的,这是现实生活中的不切实际的假设,不过还是让我们做吧)。 In other words, if people A and B are friends and B is friends with C, then A and C must also be friends. 换句话说,如果人A和B是朋友,而B是与C的朋友,那么A和C也必须是朋友。 Using this rule we can partition any group of people into friendship circles as long as we know something about the friendships in the group. 使用此规则,只要我们对某群人中的友谊有所了解,就可以将任何人划分为多个友谊圈。

Write a function networks() that takes two parameters. 编写一个带有两个参数的函数networks()。 The first parameter is the number of people in the group and the second parameter is a list of tuple objects that define friends. 第一个参数是组中的人数,第二个参数是定义朋友的元组对象列表。 Assume that people are identified by numbers 0 through n-1. 假设通过数字0到n-1来识别人。 For example, tuple (0, 2) says that person 0 is friends with person 2. The function should print the partition of people into friendship circles. 例如,元组(0,2)表示人0是与人2的朋友。此功能应将人的分区打印到友谊圈中。 The following shows several sample runs of the function: 下面显示了该函数的几个示例运行:

>>>networks(5,[(0,1),(1,2),(3,4)])#execute

Social network 0 is {0,1,2} 社交网络0为{0,1,2}

Social Network 1 is {3,4} 社交网络1为{3,4}

I am honestly pretty lost on how to start this program, any tips would be greatly appreciated. 老实说,我对如何启动该程序非常迷失,任何提示将不胜感激。

One efficient data structure you can use to solve this is a disjoint set , also known as a union-find structure. 可用于解决此问题的一种有效数据结构是disjoint set ,也称为union-find结构。 A while back I wrote one for another answer . 前一段时间,我写了另一个答案

Here's the structure: 结构如下:

class UnionFind:
    def __init__(self):
        self.rank = {}
        self.parent = {}

    def find(self, element):
        if element not in self.parent: # leader elements are not in `parent` dict
            return element
        leader = self.find(self.parent[element]) # search recursively
        self.parent[element] = leader # compress path by saving leader as parent
        return leader

    def union(self, leader1, leader2):
        rank1 = self.rank.get(leader1,1)
        rank2 = self.rank.get(leader2,1)

        if rank1 > rank2: # union by rank
            self.parent[leader2] = leader1
        elif rank2 > rank1:
            self.parent[leader1] = leader2
        else: # ranks are equal
            self.parent[leader2] = leader1 # favor leader1 arbitrarily
            self.rank[leader1] = rank1+1 # increment rank

Here's how you can use it to solve your problem: 这是解决问题的方法:

def networks(num_people, friends):
    # first process the "friends" list to build disjoint sets
    network = UnionFind()
    for a, b in friends:
        network.union(network.find(a), network.find(b))

    # now assemble the groups (indexed by an arbitrarily chosen leader)
    groups = defaultdict(list)
    for person in range(num_people):
        groups[network.find(person)].append(person)

    # now print out the groups (you can call `set` on `g` if you want brackets)
    for i, g in enumerate(groups.values()):
        print("Social network {} is {}".format(i, g))

Here's a solution based on connected components in a graph (suggested by @Blckknght ): 这是一个基于图中连接组件的解决方案(由@Blckknght建议):

def make_friends_graph(people, friends):
    # graph of friends (adjacency lists representation)
    G = {person: [] for person in people} # person -> direct friends list
    for a, b in friends:
        G[a].append(b) # a is friends with b
        G[b].append(a) # b is friends with a
    return G

def networks(num_people, friends):
    direct_friends = make_friends_graph(range(num_people), friends)
    seen = set() # already seen people

    # person's friendship circle is a person themselves 
    # plus friendship circles of all their direct friends
    # minus already seen people
    def friendship_circle(person): # connected component
        seen.add(person)
        yield person

        for friend in direct_friends[person]:
            if friend not in seen:
                yield from friendship_circle(friend)
                # on Python <3.3
                # for indirect_friend in friendship_circle(friend):
                #     yield indirect_friend

    # group people into friendship circles
    circles = (friendship_circle(person) for person in range(num_people)
               if person not in seen)

    # print friendship circles
    for i, circle in enumerate(circles):
        print("Social network %d is {%s}" % (i, ",".join(map(str, circle))))

Example: 例:

networks(5, [(0,1),(1,2),(3,4)])
# -> Social network 0 is {0,1,2}
# -> Social network 1 is {3,4}
def networks(n,lst):
groups= []
for i in range(n)
    groups.append({i})
for pair in lst:
    union = groups[pair[0]]|groups[pair[1]]
    for p in union:
        groups[p]=union
sets= set()
for g in groups:
    sets.add(tuple(g))
i=0
for s in sets:
    print("network",i,"is",set(s))
    i+=1

This is what I was looking for if anybody cares. 如果有人在乎,这就是我一直在寻找的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM