我創建了一個Graph類以及Node我測驗過的類。它正在處理基本測驗。我現在正在嘗試使用自定義輸入檔案進行測驗,但我遇到了一個錯誤,其中一些Nodes 被復制。在Graph類中,有一個集合,稱為添加正在創建的位置Nodes。Node但是,在我的決議器檔案中,我有一個檢查器,它檢查具有該值的節點之前是否已添加但它不能正常作業。
即使在下面添加哈希函式后,我仍然得到set([Alpha, Beta, Hotel, Alpha]).
我究竟做錯了什么?
測驗檔案:
directed unweighted
Alpha=Hotel
Alpha=Beta
Beta=Charlie
Charlie=Juliett
Charlie=Juliett
Delta=Foxtrot
Delta=Golf
Echo=Charlie
Echo=Delta
Foxtrot=Golf
Golf=Juliett
Golf=Alpha
Hotel=Echo
Hotel=India
India=Beta
India=Golf
Juliett=Golf
圖和節點類:
class Graph:
def __init__(self):
self.Nodes = set()
def addVertex(self, vertex):
self.Nodes.add(vertex)
def getVertices(self):
return self.Nodes
@staticmethod
def addEdgeDirect(fromEdge, toEdge, cost=1):
fromEdge.neighbors[toEdge] = cost
class Node():
def __init__(self, val = None):
self.value = val
self.neighbors = {}
def getEdges(self):
return self.neighbors.keys()
def __repr__(self):
return str(self.value)
測驗檔案決議器:
from graph import Graph, Node
graph = Graph()
file1 = open('Graphs/du.gl', 'r')
Lines = file1.readlines()
direction = Lines[0].split(" ")[0].strip()
weight = Lines[0].split(" ")[1].strip()
count = 0
if(direction == "directed"):
if(weight == "unweighted"):
for line in Lines:
count = 1
if(count == 1):
continue
node1 = Node(line.split("=")[0].strip())
node2 = Node(line.split("=")[1].strip())
if node1 not in graph.Nodes:
print("not found, to be added")
graph.addVertex(Node(node1))
if node2 not in graph.Nodes:
graph.addVertex(Node(node2))
print(graph.getVertices())
graph.addEdgeDirect(node1,node2)
# print("Line{}: {}".format(count, line.strip()))
uj5u.com熱心網友回復:
在一個set物件中,總是通過它們的物件 ID(參考)來區分。所以定義也無濟于事__hash__。
我建議:
- 使用字典而不是集合
- 僅
Node在您已經知道需要一個新實體時才創建實體——因此在檢查Nodes字典是否還沒有它之后 - 結果:將字串值傳遞給
addVertex而不是Node實體。
通過其他一些小的更改,您的代碼可能是:
class Graph:
def __init__(self):
self.nodes = {}
def addVertex(self, key):
if key not in self.nodes:
self.nodes[key] = Node(key)
return self.nodes[key]
def getVertices(self):
return self.nodes.values()
@staticmethod
def addEdgeDirect(fromEdge, toEdge, cost=1):
fromEdge.neighbors[toEdge] = cost
class Node():
def __init__(self, val=None):
self.value = val
self.neighbors = {}
def getEdges(self):
return self.neighbors.keys()
def __repr__(self):
return str(self.value)
graph = Graph()
file1 = open('du.gl', 'r')
firstline, *lines = file1.readlines()
direction, weight = firstline.split()
if direction == "directed":
if weight == "unweighted":
for line in lines:
graph.addEdgeDirect(*(graph.addVertex(key.strip())
for key in line.split("=")))
print(graph.getVertices())
附錄
在您詢問的評論中getEdges以及它如何回傳更多資訊。
這是該方法的一種變體:
def getEdges(self):
return { self: self.neighbors }
如果你這樣做:
print(graph.nodes['Alpha'].getEdges())
...它將輸出:
{Alpha: {Hotel: 1, Beta: 1}}
uj5u.com熱心網友回復:
您期望該集合應包含具有唯一名稱的節點,但您沒有指定唯一性應取決于value這些節點的屬性。
您應該將以下方法添加到您的節點類:
def __hash__(self):
return hash(self.value)
uj5u.com熱心網友回復:
有一些問題,有些與缺少型別檢查有關,有些與您的類的設計有關。
首先,你有一個Node類,你暗示的實體可能應該有一個唯一的self.value,并且它self.value應該總是一個字串(盡管這些期望不包含在代碼中)。
在另一條評論中解決了導致該set()行為的一個問題,即缺少__hash__()方法。因為看起來你可能希望兩個節點相等當且僅當它們的value引數是相同的字串時,添加
def __hash__(self):
return hash(self.value)
是需要的。但是,要set()按照您的意愿作業,您還需要添加一個__eq__()功能。
def __eq__(self, other):
return isinstance(other, Node) and self.value == other.value
我不清楚節點的“鄰居”屬性是否對其身份很重要,作為術語node,并且graph不攜帶有關類實際是什么或代表什么的資訊,因此也許也neighbors應該包含在內__eq__。
添加這些方法后,回圈的主體仍然不正確。問題線graph.addVertex(Node(node1))特別是Node(node1). 據說這是為了創建 node1 的副本,但它實際上初始化了一個新節點,其中 newnode.value 現在是 Node 的一個實體,而不是一個字串。使用型別提示和/或顯式型別檢查有助于發現這些問題,例如,向isinstance(value, str)初始化主體添加檢查。
從回圈體中替換這兩個條件,正確的版本是:
if node1 not in graph.Nodes:
graph.addVertex(node1)
if node2 not in graph.Nodes:
graph.addVertex(node2)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/438327.html
下一篇:檢查一棵樹是否為BST
