在Go语言中递归迭代结构体数组。

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

recursively iterate struct array in Go

问题

我需要遍历一个JSON文件中的所有答案选项:

{
  "questions": [
    {
      "id": 1,
      "question": "What is your marital status?",
      "answer": [
        {
          "text": "Single",
          "next_question": 2
        },
        {
          "text": "Married",
          "next_question": 3
        }
      ]
    },
    {
      "id": 2,
      "question": "Are you planning on getting married next year?",
      "answer": [
        {
          "text": "Yes",
          "next_question": 3
        },
        {
          "text": "No",
          "next_question": 5
        }
      ]
    },
    {
      "id": 3,
      "question": "How long have you been married?",
      "answer": [
        {
          "text": "Less than a year",
          "next_question": 6
        },
        {
          "text": "More than a year",
          "next_question": 4
        }
      ]
    },
    {
      "id": 4,
      "question": "Have you celebrated your one year anniversary?",
      "answer": [
        {
          "text": "Yes",
          "next_question": 7
        },
        {
          "text": "No",
          "next_question": 8
        }
      ]
    }
  ]
}

并将路径和编号写入,例如:

{
  "paths": {
    "number": 3,
    "list": [
      [
        {
          "What is your marital status?": "Single"
        },
        {
          "Are you planning on getting married next year?": "Yes/No"
        }
      ],
      [
        {
          "What is your marital status?": "Married"
        },
        {
          "How long have you been married?": "Less than a year"
        }
      ],
      [
        {
          "What is your marital status?": "Married"
        },
        {
          "How long have you been married?": "More than a year"
        },
        {
          "Have you celebrated your one year anniversary?": "Yes/No"
        }
      ]
    ]
  }
}

你可以根据需要更改JSON结构,但主要是显示所有可能的调查路径数量(paths.number),以及按问题序列和答案显示的所有可能路径(paths.list)。

所以,我将JSON解析为以下结构:

type (
   Answer struct {
      Text         string `json:"text"`
      NextQuestion int    `json:"next_question"`
   }
   Question struct {
      Id       int      `json:"id"`
      Question string   `json:"question"`
      Answer   []Answer `json:"answer"`
   }
   Input struct {
      Questions []Question `json:"questions"`
   }
)

然后尝试进行迭代:

func (input Input) Script(itterQuestion []Question, element Question) []Question {
   itterQuestion = append(itterQuestion, element)
   for i, item := range input.Questions {
      if item.Id != itterQuestion[i].Id {
         itterQuestion = append(itterQuestion, item)
      } else {
         return input.Script(itterQuestion, item)
      }
   }
   return itterQuestion
}

但我不明白如何正确编写递归函数和输出结构以生成JSON。

英文:

I need to iterate over all the answer options from a json file:

{"questions": [
  {"id": 1,
    "question": "What is your marital status?",
      "answer":[ {
        "text": "Single",
        "next_question": 2
      },
        {
        "text": "Married",
        "next_question": 3
      }]
    },
  {"id":2,
    "question": "Are you planning on getting married next year?",
    "answer":[{
      "text": "Yes",
      "next_question": 3
      },
      {
      "text": "No",
      "next_question": 5
    }]},
  {"id":3,
    "question": "How long have you been married?",
    "answer": [{
      "text": "Less than a year",
      "next_question": 6
    },
    {
      "text": "More than a year",
      "next_question": 4
    }]},
  {"id":4,
    "question":"Have you celebrated your one year anniversary?",
    "answer": [{
      "text": "Yes",
      "next_question": 7
    },
     {
      "text": "No",
      "next_question": 8
    }]}
]}

and write the paths and number, like:

{"paths": {"number": 3, "list": [
  [{"What is your marital status?": "Single"},
    {"Are you planning on getting married next year?": "Yes/No"}],
  [{"What is your marital status?": "Married"},
    {"How long have you been married?": "Less than a year"}],
  [{"What is your marital status?": "Married"},
    {"How long have you been married?": "More than a year"},
    {"Have you celebrated your one year anniversary?": "Yes/No"}]
]}}

You can change JSON structure like you want, but the main thing is to display information about the number of all possible poll paths (paths.number), and all possible paths by a sequence of questions with answers (paths.list)

So, I parse JSON into this structs:

type (
   Answer struct {
      Text         string `json:"text"`
      NextQuestion int    `json:"next_question"`
   }
   Question struct {
      Id       int      `json:"id"`
      Question string   `json:"question"`
      Answer   []Answer `json:"answer"`
   }
   Input struct {
      Questions []Question `json:"questions"`
   }
)

And try to iterate:

func (input Input) Script(itterQuestion []Question, element Question) []Question {
   itterQuestion = append(itterQuestion, element)
   for i, item := range input.Questions {
      if item.Id != itterQuestion[i].Id {
         itterQuestion = append(itterQuestion, item)
        
      } else {
         return input.Script(itterQuestion, item)
      }
   }
   return itterQuestion
}

But I don't understand how to correctly write recursive func and output struct for json.

答案1

得分: 0

由于您想创建多个路径,所以需要使用[][]Question
此外,您需要将递归函数的结果附加到返回值中,而不仅仅是返回结果。

以下是一个可行的示例:

func (input Input) Script(id int) (out [][]Question) {
	for _, q := range input.Questions {
		if q.Id == id {
			added := false // 避免最后多次添加
			for _, answer := range q.Answer {
				paths := input.Script(answer.NextQuestion)
				if len(paths) == 0 && !added {
					// 答案没有下一个问题 | 输入中找不到问题
					out = append(out, []Question{q})
					added = true
				}
				for _, path := range paths {
					// 在递归函数的每个路径前添加问题
					path = append([]Question{q}, path...)
					out = append(out, path)
				}
			}

			return out
		}
	}
	return out
}

希望对您有所帮助!

英文:

Since you want to create multiple paths there is gotta be [][]Question.
Also you have to append result from recursive function instead just returning.

Here's working example:

func (input Input) Script (id int) (out [][]Question) {
	for _, q := range input.Questions {
		if q.Id == id {
			added := false // avoid add last multiple times
			for _, answer := range q.Answer {
				paths := input.Script(answer.NextQuestion)
				if len(paths) == 0  && !added {
                    // answer has no next question | question not found in input
					out = append(out, []Question{q})
					added = true
				}
				for _, path := range paths {
					// prepend question to every path from recursive function
					path = append([]Question{q}, path...)
					out = append(out, path)
				}
			}

			return out
		}
	}
	return out
}

huangapple
  • 本文由 发表于 2022年3月25日 22:38:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/71618744.html
匿名

发表评论

匿名网友

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

确定