英文:
Stop recursive function when element is found
问题
我正在尝试解决《The Go Programming Language》一书中的一个练习题:
起始代码可以在这里找到:exercise。
我需要做的是:
修改forEachNode函数,使得pre和post函数返回一个布尔值,指示是否继续遍历。使用它来编写一个具有以下签名的函数ElementByID,该函数查找具有指定id属性的第一个HTML元素。一旦找到匹配项,函数应该停止遍历。
签名:func ElementByID(doc *html.Node, id string) *html.Node
我做了什么:
func ElementByID(doc *html.Node, id string) *html.Node {
if doc.Data == id {
fmt.Printf(" %s: %s\n", "found", doc.Data)
return doc
}
return nil
}
func startElement(n *html.Node) bool {
if n.Type == html.ElementNode {
if ElementByID(n, "a") != nil {
return true
}
fmt.Printf("%*s<%s>\n", depth*2, "", n.Data)
depth++
}
return false
}
func endElement(n *html.Node) bool {
if n.Type == html.ElementNode {
if ElementByID(n, "a") != nil {
return true
}
depth--
fmt.Printf("%*s</%s>\n", depth*2, "", n.Data)
}
return false
}
上面的代码正确吗?还是我漏掉了什么?如何在找到元素时停止遍历?
forEachNode函数是相同的,只是pre和post的签名被更改为返回一个布尔值。
英文:
I am trying to solve an exercise from The go programming language book:
The starting code can be found here: exercise.
What I need to do:
Modify forEachNode so that the pre and post functions return a boolean result indicating whether to continue the traversal. Use it to write a function ElementByID with the following signature that finds the first HTML element with the specified id attribute. The function should stop the traversal as soon as a match is found.
Signature: func ElementByID(doc *html.Node, id string) *html.Node
What I did:
func ElementByID(doc *html.Node, id string) *html.Node {
if doc.Data == id {
fmt.Printf(" %s: %s\n", "found", doc.Data)
return doc
}
return nil
}
func startElement(n *html.Node) bool {
if n.Type == html.ElementNode {
if ElementById(n, "a") != nil {
return true
}
fmt.Printf("%*s<%s>\n", depth*2, "", n.Data)
depth++
}
return false
}
func endElement(n *html.Node) bool {
if n.Type == html.ElementNode {
if ElementById(n, "a") != nil {
return true
}
depth--
fmt.Printf("%*s</%s>\n", depth*2, "", n.Data)
}
return false
}
Is the above right?, or I've missed something? How can I stop the traversal where element is found?
The forEachNode is the same, only the pre and post signature was changed to return a bool.
答案1
得分: 1
你可以创建一个闭包并“关闭”found
节点。下面是一个示例。
修改forEachNode
函数,使得pre
和post
函数返回一个布尔值,指示是否继续遍历:
func forEachNode(n *html.Node, pre, post func(n *html.Node) bool) {
if pre != nil && !pre(n) {
return
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
forEachNode(c, pre, post)
}
if post != nil && !post(n) {
return
}
}
使用它编写一个具有以下签名的ElementByID
函数,该函数查找具有指定id属性的第一个HTML元素。一旦找到匹配项,函数应该立即停止遍历:
func ElementByID(doc *html.Node, id string) *html.Node {
var found *html.Node
pre := func(n *html.Node) bool {
for _, a := range n.Attr {
if a.Key == "id" && a.Val == id {
found = n // 记录匹配的节点
return false // 停止遍历
}
}
return true
}
forEachNode(doc, pre, nil)
return found
}
英文:
You can create a closure and "close" found
node. Example below.
> Modify forEachNode so that the pre and post functions return a boolean result indicating whether to continue the traversal.:
func forEachNode(n *html.Node, pre, post func(n *html.Node) bool) {
if pre != nil && !pre(n) {
return
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
forEachNode(c, pre, post)
}
if post != nil && !post(n) {
return
}
}
> Use it to write a function ElementByID with the following signature that finds the first HTML element with the specified id attribute. The function should stop the traversal as soon as a match is found.:
func ElementByID(doc *html.Node, id string) *html.Node {
var found *html.Node
pre := func(n *html.Node) bool {
for _, a := range n.Attr {
if a.Key == "id" && a.Val == id {
found = n // memorize matching node
return false // stop traversing
}
}
return true
}
forEachNode(doc, pre, nil)
return found
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论