【问题标题】:How do I convert a list of pairs into a dictionary with each element as a key to a list of paired values?如何将对列表转换为字典,其中每个元素作为配对值列表的键?
【发布时间】:2019-08-20 17:04:07
【问题描述】:

我正在做涉及图表的课程。我有边缘列表 E=[('a','b'),('a','c'),('a','d'), ('b','c') 等 ] 和我想要一个函数将它们转换为字典形式的邻接矩阵 {'a':['b','c','d'],'b':['a', etc.} 这样我可以使用只输入这些字典的函数。

我的主要问题是我无法弄清楚如何使用循环来添加键:值而不只是覆盖列表。我的函数的先前版本会将 [] 作为所有值输出,因为 'f' 没有连接。

我试过了:

V = ['a','b','c','d','e','f']
E=[('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]

def EdgeListtoAdjMat(V,E):
    GA={}
    conneclist=[]
    for v in V:
        for i in range(len(V)):
            conneclist.append([])
            if (v,V[i]) in E:
                conneclist[i].append(V[i])
    for i in range(len(V)):
        GA[V[i]]=conneclist[i]
    return(GA)

EdgeListtoAdjMat(V,E) 输出:

{'a': [], 'b': ['b'], 'c': ['c', 'c'], 'd': ['d', 'd', 'd'], 'e': [], 'f': []}

而它应该输出:

{'a':['b','c','d'],
'b':['a','c','d'],
'c':['a','b','d'],
'd':['a','b','c'],
'e':[],
'f':[]
}

【问题讨论】:

    标签: python list dictionary type-conversion


    【解决方案1】:

    你想要达到的逻辑其实很简单:

    V = ['a','b','c','d','e','f']
    E=[('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
    
    result = {}
    for elem in V:
         tempList = []
         for item in E:
              if elem in item:
                   if elem == item[0]:
                        tempList.append(item[1])
                   else:
                        tempList.append(item[0])
         result[elem] = tempList
         tempList = []
    
    print(result)
    

    结果:

    {'a': ['b', 'c', 'd'], 'b': ['a', 'c', 'd'], 'c': ['a', 'b', 'd'], 'd': ['a', 'b', 'c'], 'e': [], 'f': []}
    

    对于V 中的每个元素,执行检查以查看该元素是否存在于E 中的任何元组中。如果存在,则将在该元组上共同形成一对的元素附加到临时列表中。检查E 中的每个元素后,更新result 字典并移动到V 的下一个元素,直到完成。

    要返回您的代码,您需要进行如下修改:

    def EdgeListtoAdjMat(V,E):
        GA={}
        conneclist=[]
        for i in range(len(V)):
            for j in range(len(V)):
                # Checking if a pair of two different elements exists in either format inside E. 
                if not i==j and ((V[i],V[j]) in E or (V[j],V[i]) in E):
                    conneclist.append(V[j])
            GA[V[i]]=conneclist
            conneclist = []
        return(GA)
    

    【讨论】:

      【解决方案2】:

      一种更有效的方法是遍历边并将两个方向的顶点追加到列表的输出字典中。使用dict.setdefault 用列表初始化每个新键。当边缘上的迭代完成时,迭代尚未在输出字典中的其余顶点以分配给它们空列表:

      def EdgeListtoAdjMat(V,E):
          GA = {}
          for a, b in E:
              GA.setdefault(a, []).append(b)
              GA.setdefault(b, []).append(a)
          for v in V:
              if v not in GA:
                  GA[v] = []
          return GA
      

      所以给定:

      V = ['a', 'b', 'c', 'd', 'e', 'f']
      E = [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
      

      EdgeListtoAdjMat(V, E)) 会返回:

      {'a': ['b', 'c', 'd'], 'b': ['a', 'c', 'd'], 'c': ['a', 'b', 'd'], 'd': ['a', 'b', 'c'], 'e': [], 'f': []}
      

      【讨论】:

        【解决方案3】:

        由于您已经在 V 中获得了顶点列表,因此很容易准备一个包含空连接列表的字典。然后,只需遍历边缘列表并添加到每一侧的数组中:

        V = ['a','b','c','d','e','f']
        E = [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
        
        GA = {v:[] for v in V}
        for v1,v2 in E:
            GA[v1].append(v2)
            GA[v2].append(v1)
        

        【讨论】:

          【解决方案4】:

          我认为你的代码不是很pythonic,你可以编写一个更易于调试且速度更快的代码,因为你使用的是python的内置库和numpy的索引。

          def EdgeListToAdjMat(V, E):
              AdjMat = np.zeros((len(V), len(V)))  # the shape of Adjancy Matrix
              connectlist = {
                  # Mapping each character to its index
                  x: idx for idx, x in enumerate(V)
              }
              for e in E:
                  v1, v2 = e
                  idx_1, idx_2 = connectlist[v1], connectlist[v2]
                  AdjMat[idx_1, idx_2] = 1     
                  AdjMat[idx_2, idx_1] = 1
          
              return AdjMat
          

          【讨论】:

            【解决方案5】:

            如果您考虑使用库,networkx 专为这些类型的网络问题而设计:

            import networkx as nx 
            
            V = ['a','b','c','d','e','f']
            E = [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
            
            G=nx.Graph(E)
            G.add_nodes_from(V)
            GA = nx.to_dict_of_lists(G)
            
            print(GA)
            
            # {'a': ['c', 'b', 'd'], 'c': ['a', 'b', 'd'], 'b': ['a', 'c', 'd'], 'e': [], 'd': ['a', 'c', 'b'], 'f': []}
            

            【讨论】:

              【解决方案6】:

              您可以使用itertools.groupby将边缘列表转换为地图

              from itertools import groupby
              from operator import itemgetter
              
              V = ['a','b','c','d','e','f']
              E = [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
              
              # add edge in the other direction. E.g., for a -> b, add b -> a
              nondirected_edges = E + [tuple(reversed(pair)) for pair in E]
              
              # extract start and end vertices from an edge
              v_start = itemgetter(0)
              v_end = itemgetter(1)
              
              # group edges by their starting vertex
              groups = groupby(sorted(nondirected_edges), key=v_start)
              # make a map from each vertex -> adjacent vertices
              mapping = {vertex: list(map(v_end, edges)) for vertex, edges in groups}
              
              # if you don't need all the vertices to be present
              # and just want to be able to lookup the connected
              # list of vertices to a given vertex at some point
              # you can use a defaultdict:
              from collections import defaultdict
              adj_matrix = defaultdict(list, mapping)
              
              # if you need all vertices present immediately:
              adj_matrix = dict(mapping)
              adj_matrix.update({vertex: [] for vertex in V if vertex not in mapping})
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-09-29
                • 2023-03-15
                相关资源
                最近更新 更多