Python转C# Revit API:新手如何实现双键权重字典的最短路径
问题描述
我是C#和API的新手,难以将实用方案转化为自身代码,希望获得指导。我的目标是找到最短路径,现有通过Connector相互连接的元素,已能找出所有可能路径,但无法实现类似Python代码中带双键的self.weights字典。
参考Python代码
start = IN[0] end = IN[1] edges = IN[2] graph = Graph() for edge in edges: graph.add_edge(edge[0],edge[1],1) class Graph(): def __init__(self): """ self.edges is a dict of all possible next nodes e.g. {'X': ['A', 'B', 'C', 'E'], ...} self.weights has all the weights between two nodes, with the two nodes as a tuple as the key e.g. {('X', 'A'): 7, ('X', 'B'): 2, ...} """ self.edges = defaultdict(list) self.weights = {} def add_edge(self, from_node, to_node, weight): # Note: assumes edges are bi-directional self.edges[from_node].append(to_node) self.edges[to_node].append(from_node) self.weights[(from_node, to_node)] = weight self.weights[(to_node, from_node)] = weight
我的C#现有代码
foreach (Connector con in cset) { if (con.IsConnected) { string key = con.Owner.Id.ToString(); if (conn_dic.ContainsKey(key)) { List<Connector> conns = conn_dic[key]; conns.Add(con); conn_dic[key] = conns; } else { conn_dic.Add(key, new List<Connector>() { con }); } } }
解决方案
C#没有Python中直接用元组当字典键的原生语法,但可以通过两种方式实现等效的双节点键权重字典:
方式1:自定义不可变节点对类(兼容所有C#版本)
创建一个不可变类存储节点对,重写Equals和GetHashCode方法以支持字典键特性:
public class NodePair { public string FromNode { get; } public string ToNode { get; } public NodePair(string from, string to) { FromNode = from; ToNode = to; } public override bool Equals(object obj) { if (obj is NodePair other) { return FromNode == other.FromNode && ToNode == other.ToNode; } return false; } public override int GetHashCode() { return HashCode.Combine(FromNode, ToNode); } }
然后实现Graph类:
using System.Collections.Generic; public class Graph { public Dictionary<string, List<string>> Edges { get; } public Dictionary<NodePair, int> Weights { get; } public Graph() { Edges = new Dictionary<string, List<string>>(); Weights = new Dictionary<NodePair, int>(); } public void AddEdge(string fromNode, string toNode, int weight) { // 添加双向边 if (!Edges.ContainsKey(fromNode)) Edges[fromNode] = new List<string>(); Edges[fromNode].Add(toNode); if (!Edges.ContainsKey(toNode)) Edges[toNode] = new List<string>(); Edges[toNode].Add(fromNode); // 添加双向权重 Weights.Add(new NodePair(fromNode, toNode), weight); Weights.Add(new NodePair(toNode, fromNode), weight); } }
方式2:使用ValueTuple(C# 7.0及以上版本支持)
C# 7.0引入的ValueTuple可以直接作为字典键,无需自定义类:
using System.Collections.Generic; public class Graph { public Dictionary<string, List<string>> Edges { get; } public Dictionary<(string From, string To), int> Weights { get; } public Graph() { Edges = new Dictionary<string, List<string>>(); Weights = new Dictionary<(string, string), int>(); } public void AddEdge(string fromNode, string toNode, int weight) { // 添加双向边 if (!Edges.ContainsKey(fromNode)) Edges[fromNode] = new List<string>(); Edges[fromNode].Add(toNode); if (!Edges.ContainsKey(toNode)) Edges[toNode] = new List<string>(); Edges[toNode].Add(fromNode); // 添加双向权重 Weights[(fromNode, toNode)] = weight; Weights[(toNode, fromNode)] = weight; } }
结合Connector数据构建Graph
修改你的现有代码,将Connector数据转换为Graph的边数据:
// 假设Connector类有Target属性指向连接的目标元素 Graph graph = new Graph(); foreach (Connector con in cset) { if (con.IsConnected) { string fromNode = con.Owner.Id.ToString(); string toNode = con.Target.Id.ToString(); // 权重可根据实际需求调整,这里暂设为1 graph.AddEdge(fromNode, toNode, 1); } }
内容的提问来源于stack exchange,提问作者Bender__SS
相关产品推荐
相关产品推荐

