Home > Software engineering >  AttributeError: 'list' object has no attribute 'items' on a undirected weighted
AttributeError: 'list' object has no attribute 'items' on a undirected weighted

Time:12-04

I'm currently learning how to implement Prim's spanning tree algorithm on an graph using an adjacency list. However, I encountered an error

AttributeError: 'list' object has no attribute 'keys'

This is my code.


import heapq
from collections import defaultdict

class Edge:
    def __init__(self, startIndex, endIndex, weight):
        self.startIndex = startIndex
        self.endIndex = endIndex
        self.weight = weight
        self.next = None

    def __str__(self):
        return "["   str(self.startIndex)   ","   str(self.endIndex)   ","   str(self.weight)   "]"


class WGraph:
    def __init__(self, size=10):
        self.size = 10
        self.nodeList = {}
        self.adjacencyMatrix = [[0] * size for i in range(size)]

    def addNode(self, name):
        """Adds node to adjacency list"""
        self.nodeList[name] = []

    def addEdge(self, startIndex, endIndex, weight):
        """Add edges for adjacency list and matrix"""
        edge1 = [endIndex, weight]
        self.nodeList[startIndex].append(edge1)
        edge2 = [startIndex, weight]
        self.nodeList[endIndex].append(edge2)

        keys = sorted(self.nodeList.keys())  # sort keys in adjacency list
        size = len(keys)  # get length of keys
        index1 = list(self.nodeList.keys()).index(startIndex)
        index2 = list(self.nodeList.keys()).index(endIndex)
        self.adjacencyMatrix[index1][index2] = weight


    def listNodes(self):
        """Display nodes in list format"""
        theList = ""
        for node in self.nodeList:
            theList  = str(node)
            theList  = " "
        return theList

    def displayAdjacency(self):
        for k, v in self.nodeList.items():
            print(str(k)   ":", end="")
            for edge in v:
                print(edge, end="")
            print()

    def minCostTree(self, vertex):
        mst = defaultdict(set)
        visited = {vertex}
        edges = [
            (cost, vertex, to)
            for to, cost in self.nodeList[vertex].items()]
        heapq.heapify(edges)

        while edges:
            cost, frm, to = heapq.heappop(edges)
            if to not in visited:
                visited.add(to)
                mst[frm].add(to)
                for to_next, cost in self.nodeList[to].items():
                    if to_next not in visited:
                        heapq.heappush(edges, (cost, to, to_next))
        return mst

graph = WGraph()
graph.addNode('A')
graph.addNode('B')
graph.addNode('C')
graph.addNode('D')
graph.addNode('E')
graph.addNode('F')
graph.addNode('G')
graph.addNode('H')
graph.addNode('I')
graph.addNode('J')

graph.addEdge('A', 'B', 4)
graph.addEdge('A', 'H', 8)
graph.addEdge('B', 'C', 8)
graph.addEdge('B', 'H', 11)
graph.addEdge('C', 'D', 7)
graph.addEdge('C', 'F', 4)
graph.addEdge('C', 'I', 2)
graph.addEdge('D', 'E', 9)
graph.addEdge('D', 'F', 14)
graph.addEdge('E', 'F', 10)
graph.addEdge('F', 'G', 2)
graph.addEdge('G', 'H', 1)
graph.addEdge('G', 'I', 6)
graph.addEdge('H', 'I', 7)

print("The min cost tree starting at A ")
print(" Expected A: A-B A-H H-G G-F F-C C-I C-D D-E Unreached J")
print(" Actually "   graph.minCostTree('A'), end="\n")

This is where the error happens

for to, cost in self.nodeList[vertex].items()]

The adjacency list is initialized as a dictionary. When I add nodes to the dictionary, it creates another list that's used to store the edges and weight. I suspect that having a list inside a dictionary and using the index() function to return the object caused this error. My goal is to return a string showing a minimum cost spanning tree with the starting node as root. However, I'm unable to figure out a way to fix this error. Any help would be appreciated!

CodePudding user response:

The error you are seeing is because you are trying to call the keys() method on a list object, but list objects do not have a keys() method.

You are trying to iterate over the items in the nodeList dictionary using for to, cost in self.nodeList[vertex].items():, but the values in the nodeList dictionary are lists, not dictionaries.

To fix this error, you can change the code to iterate over the values in the lists in the nodeList dictionary like this:

for edge in self.nodeList[vertex]:
    to, cost = edge
    if to not in visited:
        heapq.heappush(edges, (cost, to, to_next))

This way, you are getting the to and cost values from the tuples in the lists instead of trying to use the items() method on a list object.

  • Related