我在用Python重写一个数据驱动的遗留应用程序。其中一个主要表被称为“图表”,看起来是一个有向图,因此我正在探索NetworkX包,看看是否可以使用它来进行图表操作,并真正将其实现为一个图,而不是一组复杂的数组。
然而,我开始怀疑我们使用此表的方式是否不适合实际的图操作库。NetworkX的大部分功能似乎都面向以某种方式表征图本身、确定两个节点之间的最短距离等等。这些对我来说都没有意义。
我希望如果我能在这里描述实际的使用情况,有人可以告诉我我是否只是遗漏了什么——我从未真正接触过图,所以这是很有可能的——或者我是否应该探索一些其他数据结构。(如果是这样,您会建议什么?)
我们主要使用该表将用户提供的关键字字符串转换为有序的组件列表。这构成了95%的使用案例;其余5%是“给定一个部分关键字字符串,提供所有可能的完成”,以及“生成所有可能的合法关键字字符串”。哦,还要验证图表是否存在畸形。
以下是该表的编辑摘录。列是: keyword innode outnode component acs 1 20 clear default 1 100 clear noota 20 30 clear default 20 30 hst_ota ota 20 30 hst_ota acs 30 10000 clear cos 30 11000 clear sbc 10000 10199 clear hrc 10000 10150 clear wfc1 10000 10100 clear default 10100 10101 clear default 10101 10130 acs_wfc_im123 f606w 10130 10140 acs_f606w f550m 10130 10140 acs_f550m f555w 10130 10140 acs_f555w default 10140 10300 clear wfc1 10300 10310 acs_wfc_ebe_win12f default 10310 10320 acs_wfc_ccd1
给定关键字字符串“acs,wfc1,f555w”和此表,遍历逻辑是:
- 从节点1开始;“acs”在字符串中,所以转到节点20。
- 节点20没有呈现的关键字在字符串中,所以选择默认值,选取hst_ota,转到节点30。
- “acs”在字符串中,所以转到节点10000。
- “wfc1”在字符串中,所以转到节点10100。
- 只有一个选择;转到节点10101。
- 只有一个选择,所以选取acs_wfc_im123并转到节点10130。
- “f555w”在字符串中,所以选取acs_f555w并转到节点10140。
- 只有一个选择,所以转到节点10300。
- “wfc1”在字符串中,所以选取acs_wfc_ebe_win12f并转到节点10310。
- 只有一个选择,所以选取acs_wfc_ccd1并转到节点10320——不存在,所以我们完成了。
因此,组件的最终列表是 hst_ota acs_wfc_im123 acs_f555w acs_wfc_ebe_win12f acs_wfc_ccd1
我可以只从该表的innodes 和 outnodes 创建一个图,但我实在想不出如何构建关键字信息来确定在面临多种可能性时做出哪种选择。
更新以添加其他用例的示例:
- 给定字符串“acs”,返回(“hrc”、“wfc1”)作为可能的下一个选择
- 给定字符串“acs、wfc1、foo”,由于未使用的关键字而引发异常
- 返回所有可能的合法字符串:
cos acs, hrc acs, wfc1, f606w acs, wfc1, f550m acs, wfc1, f555w
验证所有节点都可以到达并且没有循环。
我可以针对前两个例证调整Alex的解决方案,但我不知道如何针对最后两个例证调整。
2、解决方案
一般目的图库绝对不适合(无论你应该做什么,如果一个节点中多个单词有意义的单词在输入字符串中——这是错误吗?——或者如果一个单词都没有并且节点没有默认值,就像示例中节点30的情况一样)。只需将表格写成从节点到元组(默认值、从词到特定值的字典)的字典,其中每个值都是元组(目标、要添加的单词)(并对特殊的“要添加的单词”使用清除)。例如:
tab = {1: (100, None), {'acs': (20, None)}),
20: ((30, 'hst_ota'), {'ota': (30, 'hst_ota'), 'noota': (30, None)}),
30: ((None, None), {'acs': (10000,None), 'cos':(11000,None)}),
等等
现在,处理此表和一个输入逗号分隔字符串很容易,这要归功于集合操作——例如:
def f(icss):
kws = set(icss.split(','))
N = 1
while N in tab:
stuff, others = tab[N]
found = kws & set(others)
if found:
# 也许当len(找到)>1时报错?
stuff = others[found.pop()]
N, word_to_add = stuff
if word_to_add is not None:
print word_to_add