Python 从元组列表生成邻接矩阵的更优雅的方法

Python 从元组列表生成邻接矩阵的更优雅的方法,python,function,graph,adjacency-matrix,Python,Function,Graph,Adjacency Matrix,假设我们从一个由元组列表表示的“友谊”图开始 friendships = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3), (3, 4),(4, 5), (5, 6), (5, 7), (6, 8), (7, 8), (8, 9)] 其中元素0是1的朋友(因此1是0的朋友) 我想从头开始构建邻接矩阵,,这种方法将始终适用于这种元组表示 我有以下(令人厌恶的)Python代码: def make_矩阵(行数、列数、条目数): 返回[[输入法]fn(i,j) 对于范

假设我们从一个由元组列表表示的“友谊”图开始

friendships = [(0, 1), (0, 2), (1, 2), (1, 3), (2,
3), (3, 4),(4, 5), (5, 6), (5, 7), (6, 8), (7, 8), (8, 9)]
其中元素0是1的朋友(因此1是0的朋友)

我想从头开始构建邻接矩阵,这种方法将始终适用于这种元组表示

我有以下(令人厌恶的)Python代码:

def make_矩阵(行数、列数、条目数):
返回[[输入法]fn(i,j)
对于范围内的j(num_cols)]
对于范围内的i(num_行)]
def邻接(连接):
新建=连接+[(x[1],x[0]),用于连接中的x]
元素=列表(设置([x[0]用于连接中的x]+[x[1]用于连接中的x]))
def测试(i,j):
如果(元素[i],元素[j])处于新的状态:
返回1
其他:返回0
返回make_矩阵(len(元素),len(元素),测试)
我知道这是低效和非常丑陋的。有没有更聪明的方法来解决这个问题?我上面给出的示例列表的输出应该是

[[0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [1, 0, 1, 1, 0, 0, 0, 0, 0, 0],
 [1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
 [0, 1, 1, 0, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 0, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 1, 0, 0, 1, 0],
 [0, 0, 0, 0, 0, 1, 0, 0, 1, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 0, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 0]]
更新: 根据其中一个答案,我有以下可能的解决方案,尽管我不知道是否更好

def调整(连接):
##第一步
temp=(为连接中的元素设置(元素[0])。并集(
设置(elem[1]用于连接中的elem)))
n=最大(温度)+1
ans=[]
##步骤2
对于i,uu在枚举中(临时):
ans.append([])
对于j,枚举中的u(临时):
ans[i]。追加(0)
##步骤3
对于成对输入连接:
ans[pair[0]][pair[1]]=1
ans[pair[1]][pair[0]]=1
返回ans

我的算法是这样的:

  • 找到最大顶点id。调用此
    n
  • 通过
    n+1
    零数组创建
    n+1
    。称之为
    M
  • 对于输入列表中的每对
    x,y
    ,设置
    M[x][y]=1
  • 为了想出这个解决方案,我首先想到了步骤3。对于给定的输入,这似乎是填充邻接矩阵最直接的方法。但是,它需要一个固定大小的二维数组。因此,问题是如何计算步骤2的
    n
    。从这里不需要太多的思考就可以看出第1步是需要的


    详细信息留给读者作为练习。

    如果您想要简短易读的解决方案(并且计划稍后使用graph),我建议您使用库。您的问题可以通过两条线来解决:

    import networkx as nx
    G = nx.Graph()
    G.add_edges_from(friendships)
    nx.to_numpy_matrix(G)
    
    它将返回numpy矩阵:

    matrix([[0., 1., 1., 0., 0., 0., 0., 0., 0., 0.],
            [1., 0., 1., 1., 0., 0., 0., 0., 0., 0.],
            [1., 1., 0., 1., 0., 0., 0., 0., 0., 0.],
            [0., 1., 1., 0., 1., 0., 0., 0., 0., 0.],
            [0., 0., 0., 1., 0., 1., 0., 0., 0., 0.],
            [0., 0., 0., 0., 1., 0., 1., 1., 0., 0.],
            [0., 0., 0., 0., 0., 1., 0., 0., 1., 0.],
            [0., 0., 0., 0., 0., 1., 0., 0., 1., 0.],
            [0., 0., 0., 0., 0., 0., 1., 1., 0., 1.],
            [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.]])
    

    nx.邻接矩阵(G)

    将返回scipy稀疏矩阵:

    <10x10 sparse matrix of type '<class 'numpy.int64'>'
        with 24 stored elements in Compressed Sparse Row format>
    
    
    
    我会:

    import numpy as np
    
    def adjacency(connections):
        n_people = max(sum(connections, ())) + 1
        mat = np.zeros((n_people, n_people), dtype='int')
        for friend1, friend2 in connections:
            mat[friend1, friend2] = 1
            mat[friend2, friend1] = 1
        return mat
    
    如果“从头开始”的意思是你不想使用numpy:

    def adjacency(connections):
        n_people = max(sum(connections, ())) + 1
        mat = [[0 for _ in range(n_people)] for _ in range(n_people)]
        for friend1, friend2 in connections:
            mat[friend1][friend2] = 1
            mat[friend2][friend1] = 1
        return mat
    

    我不是一个Python程序员,但有点像

    def to_adjacency_matrix(pairs):
      size = 1 + max(map(max, pairs))
      a = [[0 for j in range(size)] for i in range(size)]
      for i, j in pairs:
        a[i][j] = a[j][i] = 1
      return a
    

    你提前知道顶点的数量吗?@Code peedient no,这是挑战的一部分,也是我从头开始在middlefrom中定义总元素的原因-这是否意味着你实际上只在寻找本机解决方案,而库已经不存在了?@paritossingh是的。我对具有可调用的邻接函数的图形/网络库不感兴趣。
    n
    应该比最大值多一个ID@TavianBarnes或者,数组的维度应该比
    n
    @AndresMejia多一个是的,该代码看起来非常接近地翻译了我的伪代码。然而,逻辑上有一个缺陷。例如,如果
    连接
    [(1,2)、(5,3)]
    ,那么
    n
    应该是6。我把它作为练习留给你去发现问题。你可能会发现这很有帮助。@AndresMejia“我仍然有一种唠叨的怀疑,那就是它并不像可能的那么好”这种感觉会困扰你,不管你编写了多长时间的代码。我们只是随着经验的积累而提高,有时“足够好”就足够好了。@Code学徒好吧,也许你是对的。我将继续:)另外,您对
    大小的计算不太正确。例如,如果
    pairs=[(1,10)、(5,2)]
    则将分配大小
    6
    ,而不是
    11
    的正确值。注意
    reduce(max,foo)
    相当于
    max(foo)
    。提示:对于初始化
    a
    ,可以使用
    *
    操作符简化内部列表理解
    a=[[0]*size]for i in-range(size)]
    @code peedient抱歉键入
    reduce
    在思考
    map
    @code peedient时,我也确实最初编写了
    [[0]*size]
    ,然后对其进行了更改。不能说
    [[0]*size]*size
    ,因为这是对同一数组的引用数组。因此,上面的方法似乎更简单。