Pushing nested and manipulated array Data onto another array

I have been going over this for some time and I cant seem to get it working as required.

What I have:

  1. I have an array of questions under which is a nested array of answers like this:
    0: question 1
    answers:
    0:
    answer_id: “1”
    ans_index: “A”
    1:
    answer_id: “2”
    ans_index: “B”
    1: question 2
    etc…

What I need to do:

  1. I need to collect “ans_index” for all answers under each question so I have something like "chosen_index: “A, B, C …”
  2. Push each array of indices under each question.

What I get:
With the function below, I get everything right except that the values for "ans_index include everything from all answers in all questions rather than answers under each question.

This is my component TS Function:

  testAnswers(){

    this.my_answers = this.questionWanswers; //contains all questions - each with array of answers

    for(var k=0; k<this.my_answers.length; k++){
      this.current_question = this.my_answers[k]; //questions 

      this.qn_answers = this.my_answers[k].answers; //answers array

        for(var l=0; l<this.qn_answers.length; l++){
          this.qn_answers[l].selected = true; //not important for now
          
            this.chosen_index.push([l] + " " + this.qn_answers[l].ans_index); // PROBLEM: I need to create an array of ans_index for each question (one item from each answer);
            
          }

        this.current_question.order.push({"chosen_order" : this.chosen_index}); //pushing the array of ans_index onto each separate question, instead - all questions receive the same ans_index array combined from all questions
        
        }

        console.log('My answers', this.my_answers);
        // save to db
      //  this.saveTest();
    }

This what is recorded in the console:
58

From the data in the image above: chosen_order should be 0 - 2 under question 1 because it has 3 answers, and 3-6 because question two has 4 answers but all seven show up under all 2 questions.

Please help. I can elaborate further if need be. Thanks!

A language better-designed than JavaScript would make it harder to write code like this, so the onus is unfairly on the programmer here. A rule I like to follow is that for functions like this, which are effectively just munging data around, they should be so self-contained that they could be declared static. IOW, the function should take everything it needs as a parameter, and return its result. It should never touch this at all. Also, taking the time to declare interfaces and follow naming conventions as early as you can makes the code more readable (I’m going to assume that the source data is not under your control - if it is, I would do this modification more aggressively at the source so you’re not doing this work at all in the Ionic app). So, how about something like this?

interface AnswerDown {
  answer_id: string;
  ans_index: string;
}
interface QuestionDown {
  questionText: string;
  question_desc: string;
  question_id: string;
}
interface Answer {
  value: number;
  label: string;
}
interface Question {
  id: string;
  prompt: string;
  description: string;
  answers: Answer[];
}

mogrifyAnswer(incoming: AnswerDown): Answer {
  return {
    value: incoming.answer_id,
    label: incoming.ans_index,
  };
}
mogrifyQuestion(incoming: QuestionDown): Question {
  return {
    id: incoming.question_id,
    prompt: incoming.questionText,
    description: incoming.question_desc,
    answers: incoming.map(a => mogrifyAnswer(a))
  };
}
mogrifyTest(incoming: QuestionDown[]): Question[] {
  return incoming.map(q => mogrifyQuestion(q));
}

A couple of notes:

  • I’ve deliberately used label/value naming, eschewing existing “id” and “index” because they are used unconventionally as is (“index” should always be a number, and “id” should always be unique, neither of these seems to be the case here).
  • I’ve also kept label and value separate instead of turning them into a single string separated by a space in your example. Based on my experience with writing a bunch of questionnaire apps over the years, you are just going to end up splitting that string out and using it to look up one part of the other somewhere else, so it is best to preserve them as separate fields throughout the app. If you really really just want the “0 A”-type string instead of the object I’ve declared as Answer, it should be obvious how to get there.
1 Like

Thanks so much for the time you put into writing the solution and the explanation. I didn’t get the notification when you added the response so I just landed on this when checking. Let me take some good time to study your approach, and will update you on my progress. Thank you @rapropos This means a lot!

Kind regards,
Philip.