Map array and include items according to ID using MAP and FILTER

I have two arrays:

The first has some issues, eg:

Questions array:

[
    {
        "id": 2,
        "question": "Questão 1:",
        "essay_question": false,
        "value": "2.00"
    },
    {
        "id": 3,
        "question": "Questão 2:",
        "essay_question": false,
        "value": "1.00"
    },
    {
        "id": 4,
        "question": "Questão 3:",
        "essay_question": false,
        "value": "1.00"
    }
]

And the second has the options of choices for the questions above:

Options array:

[
    {
        "id": 1,
        "option": "Opção A",
        "correct": false,
        "question_id": 2
    },
    {
        "id": 4,
        "option": "Opção B",
        "correct": true,
        "question_id": 2
    },
    {
        "id": 6,
        "option": "Opção A",
        "correct": false,
        "question_id": 3
    },
    {
        "id": 7,
        "option": "Opção B",
        "correct": true,
        "question_id": 3
    },
    {
        "id": 9,
        "option": "Opção A",
        "correct": false,
        "question_id": 4
    },
    {
        "id": 12,
        "option": "Opção B",
        "correct": true,
        "question_id": 4
    }
]

I need to create a new array by joining these two as follows: Comparing the question ID with the option id and including the options within the question array.

Eg.

[
  {
    id: 2,
    question: 'Questão 1:',
    essay_question: false,
    value: '2.00',
    options: [
      {
        id: 1,
        option: 'Opção A',
        correct: false,
        question_id: 2,
      },
      {
        id: 4,
        option: 'Opção B',
        correct: true,
        question_id: 2,
      },
    ],
  },
];

I’m trying to do the following:

const questions = question.map((q) => {
  if (options.filter((opt) => opt.question_id === q.id))
    return { ...q.dataValues, options: opt.dataValues };
  return { ...q.dataValues, options: null };
})

The map and filter worked, the problem is time to put the options array found inside the questions array. I’m getting the error: “‘opt’ is not defined.”

Answer

When you do this:

if (options.filter((opt) => opt.question_id === q.id))

The opt variable only exists within the scope of the filter function:

(opt) => opt.question_id === q.id

So when you get to your return, opt no longer exists:

return { ...q.dataValues, options: opt.dataValues };

You could create a merged question/options object using map and filter:

const merged = questions.map(
  q => ({
    ...q, // include the question properties
    options: [
      // copy the options with matching question_id
      ...options.filter(({question_id}) => question_id === q.id)
    ]
  })
);

const questions = [
    {
        "id": 2,
        "question": "Questão 1:",
        "essay_question": false,
        "value": "2.00"
    },
    {
        "id": 3,
        "question": "Questão 2:",
        "essay_question": false,
        "value": "1.00"
    },
    {
        "id": 4,
        "question": "Questão 3:",
        "essay_question": false,
        "value": "1.00"
    }
];

const options = [
    {
        "id": 1,
        "option": "Opção A",
        "correct": false,
        "question_id": 2
    },
    {
        "id": 4,
        "option": "Opção B",
        "correct": true,
        "question_id": 2
    },
    {
        "id": 6,
        "option": "Opção A",
        "correct": false,
        "question_id": 3
    },
    {
        "id": 7,
        "option": "Opção B",
        "correct": true,
        "question_id": 3
    },
    {
        "id": 9,
        "option": "Opção A",
        "correct": false,
        "question_id": 4
    },
    {
        "id": 12,
        "option": "Opção B",
        "correct": true,
        "question_id": 4
    }
];

const merged = questions.map(
  q => ({...q, options: [...options.filter(({question_id}) => question_id === q.id)] })
);

console.log(merged);