这是一种方法:
structure StringKey =
struct
type ord_key = string
val compare = String.compare
end
structure Map = RedBlackMapFn(StringKey)
fun changState l =
let fun lp(l, map, max) =
case l
of nil => nil
| (s1,s2)::l' =>
case (Map.find(map, s1), Map.find(map, s2))
of (SOME i1, SOME i2) => (i1, i2)::lp(l', map, max)
| (NONE, SOME i) => (max, i)::lp(l', Map.insert(map, s1, max), max+1)
| (SOME i, NONE) => (i, max)::lp(l', Map.insert(map, s2, max), max+1)
| (NONE, NONE) =>
if s1 <> s2
then (max, max+1)::lp(l', Map.insert(Map.insert(map, s1, max), s2, max+1), max+2)
else (max, max)::lp(l', Map.insert(map, s1, max), max+1)
in lp(l, Map.empty, 0) end
这里lp 获取字符串对列表、一个将字符串与整数关联的映射以及一个变量max,它跟踪下一个未使用的数字。在每次迭代中,我们在映射中查找两个字符串。如果找到它们,则返回该整数,否则,使用下一个可用的整数。最后一种情况,映射中不存在任何字符串,我们需要检查字符串是否相等,如果您的输入是[("s0", "s0")],我们期望[(0, 0)]。如果它们相等,我们将它们映射到相同的数字,否则创建不同的数字。
如果您不熟悉仿函数,前 5 行正在创建一个满足 ORD_KEY 签名的结构。您可以在文档中找到更多详细信息
- http://www.smlnj.org/doc/smlnj-lib/Manual/ord-map.html
- http://www.smlnj.org/doc/smlnj-lib/Manual/ord-key.html#ORD_KEY:SIG:SPEC
通过将ReBlackMapFn 函子应用于StringKey 结构,它创建了一个新的映射结构(实现为红黑树),将字符串映射到'a 类型的事物