【发布时间】:2022-01-11 17:15:18
【问题描述】:
我正在尝试构造一个这样定义的不可变 Trie:
case class Trie(children: Map[Char, Trie] = Map.empty[Char, Trie], value: Option[String] = None)
使用以下扩展方法:
extension (t: Trie)
def addAll(words: Seq[String]): Trie =
words.foldLeft(new Trie())(_.insert(_))
def insert(word: String): Trie =
var cur = t
word.foreach(c => {
if !cur.children.contains(c) then
cur = cur.copy(children = cur.children + (c -> new Trie()))
end if
cur = cur.children.get(c).get
})
cur.copy(value = Some(word))
我目前的问题是 insert 方法:我尝试了许多不同的方法,但我所有的尝试都未能返回 Trie 的根,即我无法在这样的从根节点到叶子的整个分支与新插入的节点一起复制的方式。
为了进一步说明,如下:
@main def hello: Unit =
println(new Trie().insert("bot").insert("bat"))
简单地导致:Trie(Map(),Some(bat))
我是 Scala 和 FP 的新手,所以我不确定这里的最佳方法。
【问题讨论】:
-
您需要使用 Zipper:en.wikipedia.org/wiki/Zipper_(data_structure)。这里有一个 Scala 2 实现:github.com/stanch/zipper。看看它是如何工作的。
-
value成员的目的/功能是什么?在.insert("in").insert("it")之后,根节点('i'节点)value应该是什么,为什么? -
@jwvh
value用于指示当前节点是否为终端节点,表示从根到该节点的路径代表我们的 trie 中的一个完整单词。例如,在调用.insert("in").insert("it")之后,我们会得到类似 ->Trie(Map(i -> Trie(Map(n -> Trie(Map(), Some(in)))), t -> Trie(Map(), Some(it)), None) -
@EmilianoMartinez 感谢您的提示!我在这里遇到了一个兔子洞,目前正在研究可能使用单片眼镜/镜头来根据需要更新节点。如果我成功了,会更新我的帖子。
标签: scala tree immutability trie