如何绕过深层次的 XML,而不使用嵌套循环?

huangapple go评论2521阅读模式
英文:

How to bypass deep xml, no nested loops?

问题

我有一个深层嵌套的 XML 对象:

  1. type Obj struct{
  2. Scripts []*Script `xml:"scripts"`
  3. }
  4. type Script struct{
  5. ID string `xml:"id"`
  6. Tables []*Table `xml:"tables"`
  7. }
  8. type Table struct{
  9. Elements []*Element `xml:"elements"`
  10. Tables []*Table `xml:"tables"`
  11. }
  12. type Element struct{
  13. Key string `xml:"key"`
  14. Val string `xml:"val"`
  15. }

我需要从对象中获取具有正确键的 Element 列表。如何在没有嵌套循环的情况下完成这个任务:

  1. for _, s := range obj {
  2. if s.ID == "requireID" {
  3. for _, table := range s.Tables {
  4. for _, t := range table.Tables {
  5. for _, el := range t.Elements {
  6. if el.Key == "requireKey" {
  7. elements = append(elements, el)
  8. }
  9. }
  10. }
  11. }
  12. }
  13. }
英文:

I have deep nested xml object:

  1. type Obj struct{
  2. Scripts []*Script `xml:"scripts"`
  3. }
  4. type Script struct{
  5. ID string `xml:"id"`
  6. Tables []*Table `xml:"tables"`
  7. }
  8. type Table struct{
  9. Elements []*Element `xml:"elements"`
  10. Tables []*Table `xml:"tables"`
  11. }
  12. type Element struct{
  13. Key string `xml:"key"`
  14. Val string `xml:"val"`
  15. }

I need to get a list of Element from Object with the right keys.How can this be done without a nested loop:

  1. for _, s:= range obj{
  2. if s.ID == "requireID"{
  3. for _, table:= range s.Tables{
  4. for _, t:= range table.Tables{
  5. for _, el:= range t.Elements{
  6. if el.Key == "requireKey"{
  7. elements = elements.append(elements, el)
  8. }
  9. }
  10. }
  11. }
  12. }
  13. }
  14. }

答案1

得分: 2

这是一个使用堆栈的完整工作解决方案。它比使用嵌套循环更复杂:

  1. package main
  2. import (
  3. "encoding/xml"
  4. "fmt"
  5. )
  6. type Obj struct {
  7. Scripts []*Script `xml:"scripts>script"`
  8. }
  9. type Script struct {
  10. ID string `xml:"id"`
  11. Tables []*Table `xml:"tables>table"`
  12. }
  13. type Table struct {
  14. Elements []*Element `xml:"elements>element"`
  15. Tables []*Table `xml:"tables>table"`
  16. }
  17. type Element struct {
  18. Key string `xml:"key"`
  19. Val string `xml:"val"`
  20. }
  21. func main() {
  22. // 示例 XML 数据
  23. xmlData := `
  24. <obj>
  25. <scripts>
  26. <script>
  27. <id>requireID</id>
  28. <tables>
  29. <table>
  30. <elements>
  31. <element>
  32. <key>requireKey</key>
  33. <val>value1</val>
  34. </element>
  35. </elements>
  36. <tables>
  37. <table>
  38. <elements>
  39. <element>
  40. <key>requireKey</key>
  41. <val>value2</val>
  42. </element>
  43. </elements>
  44. </table>
  45. </tables>
  46. </table>
  47. </tables>
  48. </script>
  49. </scripts>
  50. </obj>
  51. `
  52. var obj Obj
  53. err := xml.Unmarshal([]byte(xmlData), &obj)
  54. if err != nil {
  55. fmt.Println("Error:", err)
  56. return
  57. }
  58. // 调用迭代函数查找具有特定 ID 和 Key 的元素
  59. elements := findElements("requireID", "requireKey", &obj)
  60. for _, el := range elements {
  61. fmt.Println("Element Key:", el.Key, "Value:", el.Val)
  62. }
  63. }
  64. // 辅助函数,将切片转换为 []interface{} 切片
  65. func toInterfaceSlice(slice interface{}) []interface{} {
  66. s := make([]interface{}, 0)
  67. switch slice.(type) {
  68. case []*Script:
  69. for _, v := range slice.([]*Script) {
  70. s = append(s, v)
  71. }
  72. case []*Table:
  73. for _, v := range slice.([]*Table) {
  74. s = append(s, v)
  75. }
  76. case []*Element:
  77. for _, v := range slice.([]*Element) {
  78. s = append(s, v)
  79. }
  80. }
  81. return s
  82. }
  83. func findElements(requiredID, requiredKey string, rootObj interface{}) []*Element {
  84. var elements []*Element
  85. stack := []interface{}{rootObj}
  86. for len(stack) > 0 {
  87. // 从堆栈中弹出顶部元素
  88. obj := stack[len(stack)-1]
  89. stack = stack[:len(stack)-1]
  90. switch v := obj.(type) {
  91. case *Obj:
  92. for _, script := range v.Scripts {
  93. if script.ID == requiredID {
  94. stack = append(stack, script)
  95. }
  96. }
  97. case *Script:
  98. stack = append(stack, toInterfaceSlice(v.Tables)...)
  99. case *Table:
  100. for _, el := range v.Elements {
  101. if el.Key == requiredKey {
  102. elements = append(elements, el)
  103. }
  104. }
  105. stack = append(stack, toInterfaceSlice(v.Tables)...)
  106. }
  107. }
  108. return elements
  109. }

希望对你有帮助!

英文:

This is a complete working solution using stack. It is more complex than using nested loops:

  1. package main
  2. import (
  3. &quot;encoding/xml&quot;
  4. &quot;fmt&quot;
  5. )
  6. type Obj struct {
  7. Scripts []*Script `xml:&quot;scripts&gt;script&quot;`
  8. }
  9. type Script struct {
  10. ID string `xml:&quot;id&quot;`
  11. Tables []*Table `xml:&quot;tables&gt;table&quot;`
  12. }
  13. type Table struct {
  14. Elements []*Element `xml:&quot;elements&gt;element&quot;`
  15. Tables []*Table `xml:&quot;tables&gt;table&quot;`
  16. }
  17. type Element struct {
  18. Key string `xml:&quot;key&quot;`
  19. Val string `xml:&quot;val&quot;`
  20. }
  21. func main() {
  22. // Example XML data
  23. xmlData := `
  24. &lt;obj&gt;
  25. &lt;scripts&gt;
  26. &lt;script&gt;
  27. &lt;id&gt;requireID&lt;/id&gt;
  28. &lt;tables&gt;
  29. &lt;table&gt;
  30. &lt;elements&gt;
  31. &lt;element&gt;
  32. &lt;key&gt;requireKey&lt;/key&gt;
  33. &lt;val&gt;value1&lt;/val&gt;
  34. &lt;/element&gt;
  35. &lt;/elements&gt;
  36. &lt;tables&gt;
  37. &lt;table&gt;
  38. &lt;elements&gt;
  39. &lt;element&gt;
  40. &lt;key&gt;requireKey&lt;/key&gt;
  41. &lt;val&gt;value2&lt;/val&gt;
  42. &lt;/element&gt;
  43. &lt;/elements&gt;
  44. &lt;/table&gt;
  45. &lt;/tables&gt;
  46. &lt;/table&gt;
  47. &lt;/tables&gt;
  48. &lt;/script&gt;
  49. &lt;/scripts&gt;
  50. &lt;/obj&gt;
  51. `
  52. var obj Obj
  53. err := xml.Unmarshal([]byte(xmlData), &amp;obj)
  54. if err != nil {
  55. fmt.Println(&quot;Error:&quot;, err)
  56. return
  57. }
  58. // Call the iterative function to find elements with specific ID and Key
  59. elements := findElements(&quot;requireID&quot;, &quot;requireKey&quot;, &amp;obj)
  60. for _, el := range elements {
  61. fmt.Println(&quot;Element Key:&quot;, el.Key, &quot;Value:&quot;, el.Val)
  62. }
  63. }
  64. // Helper function to convert slice to []interface{} slice
  65. func toInterfaceSlice(slice interface{}) []interface{} {
  66. s := make([]interface{}, 0)
  67. switch slice.(type) {
  68. case []*Script:
  69. for _, v := range slice.([]*Script) {
  70. s = append(s, v)
  71. }
  72. case []*Table:
  73. for _, v := range slice.([]*Table) {
  74. s = append(s, v)
  75. }
  76. case []*Element:
  77. for _, v := range slice.([]*Element) {
  78. s = append(s, v)
  79. }
  80. }
  81. return s
  82. }
  83. func findElements(requiredID, requiredKey string, rootObj interface{}) []*Element {
  84. var elements []*Element
  85. stack := []interface{}{rootObj}
  86. for len(stack) &gt; 0 {
  87. // Pop the top element from the stack
  88. obj := stack[len(stack)-1]
  89. stack = stack[:len(stack)-1]
  90. switch v := obj.(type) {
  91. case *Obj:
  92. for _, script := range v.Scripts {
  93. if script.ID == requiredID {
  94. stack = append(stack, script)
  95. }
  96. }
  97. case *Script:
  98. stack = append(stack, toInterfaceSlice(v.Tables)...)
  99. case *Table:
  100. for _, el := range v.Elements {
  101. if el.Key == requiredKey {
  102. elements = append(elements, el)
  103. }
  104. }
  105. stack = append(stack, toInterfaceSlice(v.Tables)...)
  106. }
  107. }
  108. return elements
  109. }

huangapple
  • 本文由 发表于 2023年7月30日 18:30:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76797339.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定