簡體   English   中英

列出我無法弄清楚的 Python 中的問題

[英]List Problem in Python that I couldn't figure out

我有 10 個不同的列表,它們的數字從 0 到 10。這 10 個列表中的每一個都是“人”,它們包含的數字是“朋友”。 數字是他們的ID。 所以我有這樣的事情:

person = 0   friend = 5
person = 1   friend = 2
person = 1   friend = 3
person = 1   friend = 4
person = 1   friend = 6
person = 1   friend = 8
person = 2   friend = 1
person = 2   friend = 4
person = 2   friend = 6
person = 2   friend = 7
person = 2   friend = 9
person = 3   friend = 1
person = 3   friend = 6
person = 3   friend = 8
person = 4   friend = 1
person = 4   friend = 2
person = 4   friend = 6
person = 4   friend = 7
person = 4   friend = 9
person = 5   friend = 0
person = 6   friend = 1
person = 6   friend = 2
person = 6   friend = 3
person = 6   friend = 4
person = 6   friend = 8
person = 7   friend = 2
person = 7   friend = 4
person = 7   friend = 9
person = 8   friend = 1
person = 8   friend = 3
person = 8   friend = 6
person = 9   friend = 2
person = 9   friend = 4
person = 9   friend = 7

現在我想找到一個人的朋友的朋友。 我的意思是我想要一個這樣的 output。

人 0 與 5 相關

人 1 與 2、3、4、6、8 以及這些朋友的朋友相關。 所以 output 必須是這樣的:

人 1 與 2(4, 6, 7, 9), 3(6, 8), 4(2, 6, 7, 9), 6(2, 3, 4, 8), 8(3, 6) 相關)。 還有朋友的朋友的朋友喜歡:

第 1 個人與 2(4(2,6,7,9), 6(1,3,4,8).........

然后我將從列表中刪除重復的數字,這樣我就會有類似的東西:

人 1 與 2、3、4、6、7、8、9 有關系。因為人 1 與他們所有人都有關系,甚至是間接的。 我不確定我是否能夠解釋自己,但你可以問我不清楚的地方。 謝謝你的時間。

假設您的每個人的朋友列表存儲如下:

friends = {
    0: [5],
    1: [2, 3, 4, 6, 8],
    # and so on as in your question
    9: [2, 4, 7]
}

然后,您可以使用廣度優先搜索深度優先搜索算法的變體,在此有向圖中找到一個人的連通分量。

def related_persons(person):
    visited = {person}
    to_be_investigated = {person}
    while to_be_investigated:
        current_person = to_be_investigated.pop()
        for friend in friends[current_person]:
            if friend not in visited:
                visited.add(friend)
                to_be_investigated.add(friend)
    return visited

此代碼比您鏈接到的代碼更短更簡單。

編輯:對於一個非常好的 python 圖形庫,看看 NetworkX。 它還具有您想要的功能 如果您只需要這個 function,我不建議您使用它,但它可能有助於深入分析您的友誼圖。

提示:你正在嘗試做的就像在人際網絡上進行廣度優先搜索 為了更好地表示這個網絡,您可以嘗試制作一個字典映射person -> set_of_friends

讓我們首先將您的數據放入兩個列表, personsfriends

>>> persons = [0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9]
>>> friends = [5, 2, 3, 4, 6, 8, 1, 4, 6, 7, 9, 1, 6, 8, 1, 2, 6, 7, 9, 0, 1, 2, 3, 4, 8, 2, 4, 9, 1, 3, 6, 2, 4, 7]

現在讓我們構建從每個人到他們朋友的映射。

>>> friend_dict = {key:{v for i,v in enumerate(friends) if persons[i] == key} for key in set(persons)}
>>> friend_dict
{0: {5},
 1: {2, 3, 4, 6, 8},
 2: {1, 4, 6, 7, 9},
 3: {1, 6, 8},
 4: {1, 2, 6, 7, 9},
 5: {0},
 6: {1, 2, 3, 4, 8},
 7: {2, 4, 9},
 8: {1, 3, 6},
 9: {2, 4, 7}}

有關如何使用 NumPy 加速此問題的小提示,請參閱此問題(無恥插件)。 或者,如果您使用pandas ,您可以使用groupby()獲取此信息。 不管怎樣,現在我們要遍歷字典兩次(一次是給你的朋友,一次是給他們的朋友)。

>>> for person in friend_dict: 
...     friends_of_friends = set()
...     for friend in friend_dict[person]:                 # For each of my friends,
...         friends_of_friends.update(friend_dict[friend]) # look up their friends.
...     print(person, friends_of_friends)
...
0 {0}
1 {1, 2, 3, 4, 6, 7, 8, 9}
2 {1, 2, 3, 4, 6, 7, 8, 9}
3 {1, 2, 3, 4, 6, 8}
4 {1, 2, 3, 4, 6, 7, 8, 9}
5 {5}
6 {1, 2, 3, 4, 6, 7, 8, 9}
7 {1, 2, 4, 6, 7, 9}
8 {1, 2, 3, 4, 6, 8}
9 {1, 2, 4, 6, 7, 9}

現在您知道了每個人的朋友 ( friend_dict ),並且您剛剛找到了每個人的朋友的朋友。

請注意,0 和 5 相互連接,但沒有其他連接。 看起來其他所有人最終都與其他人聯系在一起。 你現在看到遞歸可能派上用場了嗎? 您希望不斷地反復瀏覽字典,直到與某人相關聯的每一組人開始發生變化。 讓我們把它們放在一起。

>>> def step_through(friend_dict): 
...     new_friend_dict = friend_dict.copy() 
...     for person in friend_dict: 
...         for friend in friend_dict[person].copy():  
...             new_friend_dict[person].update(friend_dict[friend])  
...     if new_friend_dict != friend_dict: 
...         return step_through(friend_dict) 
...     else: 
...         return new_friend_dict 
...
>>> step_through(friend_dict)
{0: {0, 5},
 1: {1, 2, 3, 4, 6, 7, 8, 9},
 2: {1, 2, 3, 4, 6, 7, 8, 9},
 3: {1, 2, 3, 4, 6, 7, 8, 9},
 4: {1, 2, 3, 4, 6, 7, 8, 9},
 5: {0, 5},
 6: {1, 2, 3, 4, 6, 7, 8, 9},
 7: {1, 2, 3, 4, 6, 7, 8, 9},
 8: {1, 2, 3, 4, 6, 7, 8, 9},
 9: {1, 2, 3, 4, 6, 7, 8, 9}}

不過,您真正想要的是廣度優先搜索,這樣您就不會一直爬過相同的路徑(請參閱@BurningKarl 的回答)。 您還可以通過跟蹤每次遍歷的路徑來改進這一點(1 是 9 的朋友,因為 x 的朋友是 x 的朋友......)。

最后,正如@BurningKarl 提到的,使用networkx完成整個過程非常容易(您可能必須pip install networkx )。

>>> import networkx as nx

>>> persons = [0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9]
>>> friends = [5, 2, 3, 4, 6, 8, 1, 4, 6, 7, 9, 1, 6, 8, 1, 2, 6, 7, 9, 0, 1, 2, 3, 4, 8, 2, 4, 9, 1, 3, 6, 2, 4, 7]
>>> friend_dict = {key:{v for i,v in enumerate(friends) if persons[i] == key} for key in set(persons)}

>>> graph = nx.Graph(friend_dict)
>>> list(nx.connected_components(graph))
[{0, 5}, {1, 2, 3, 4, 6, 7, 8, 9}]

Karl 和 SMcQ 解決方案很好。 我用這個解決了我的問題。 https://www.geeksforgeeks.org/connected-components-in-an-undirected-graph/ 還嘗試了其他方法,所有方法都運行良好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM