使用即时解析器的与空间相关的好处是否超过了预先生成的查找表的时间相关优势?
长版:
我正在创作一个化学参考工具,并且包含一个能够自动命名符合特定模式的公式的功能;例如C[n]H[2n+2] => [n]ane
;其中[n]
是LHS的整数;以及RHS上一系列名称的索引。 (meth
,eth
,...)
据我所知,这可以通过以下两种方式之一实现:
我预先生成formula <=> name
对的键/值双查找字典;应用程序启动时(启动速度较慢)或使用应用程序发布的静态列表(较慢的下载)。
通过自定义解析器即时评估公式。
方法1。 name =&gt;公式查找变得更简单一个数量级;但是,除非我想在应用程序中发送数十兆字节的数据,否则生成器必须具有n
的预设值和相当低的值。
复合这是一个事实,公式可以有几个术语;例如C[n]H[2n+1]OC[n']H[2n'+1]
;对于这些中的每一个,可能匹配的数量随n
几何增加。此外,使用这种方法会像任何人一样吃RAM。
方法2。让我使用相当小的查找表支持相当大的n
值,但是使name =&gt;公式查找有点复杂。与使用该应用程序发送的预生成文件相比,它还允许我更正生成逻辑中的错误,而无需发送新的数据文件。
这还要求每个公式与几个规则的粗略测试相匹配,确定是否适合;如果有很多规则,花费时间可能会导致界面明显减慢。
那么问题是:
在我没有考虑到的权衡中是否有任何考虑因素,或者我未考虑过的方法?
使用动态解析器的好处是否证明了实施复杂性的增加?
答案 0 :(得分:1)
你应该采用第二种方法。
一种可能的解决方案是贪心算法。将您的转换集定义为正则表达式(用于测试模式)和赋予regexp匹配对象的函数,并返回转换后的字符串。
正则表达式不够强大,无法直接处理您想要的内容。相反,你必须做类似的事情:
m = re.match(r"C\[(\d+)\]H\[(\d+)]\]", formula)
if m:
C_count, H_count = int(m.group(1)), int(m.group(2))
match_size = len(m.group(0))
if C_count*2+2 == H_count:
replacement = alkane_lookup[C_count]
elif C_count*2 == H_count:
replacement = alkene_lookup[C_count]
...
else:
replacement = m.group(0) # no replacement available
(加上其他可能性更多)
然后将其嵌入一个看似如下的循环中:
formula = "...."
new_formula = ""
while formula:
match_size, replacement = find_replacement(formula)
new_formula += replacement
formula = formula[match_size:]
(你需要处理没有匹配的情况。一种可能的方法是在find_replacement()的末尾包含所有可能元素的列表,它只返回下一个元素并计数。)
这是一种贪心算法,不保证最小的解决方案。这更复杂,但由于化学家自己对正确的形式有不同的想法,我不会太担心它。