recursively iterate struct array in Go

Issue

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.

Solution

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
}

Answered By – medasx

Answer Checked By – Katrina (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.