Map array and include ID items using MAP and FILTER

Asked

Viewed 54 times

0

I have two arrays:

The first has some questions, ex:

Array 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"
    }
]

And the second has the choices options for the above issues:

Array 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
    }
]

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

Ex:

[
  {
    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 it this way:

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 array options found inside the array questions. I am receiving error: "'opt' is not defined."

  • 2

    The block of if in if (options.filter((opt) => opt.question_id === q.id)) { ... } always run pq the method Array.prototype.filter at all times returns an array (which is a value Truthy in Javascript, which allows entry into the conditional in question). In addition, you stated opt as a parameter of the predicate passed to filter, which causes the subsequent error to which you refer. The code, if corrected, works, although I can count on some improvements to performance, since currently has complexity O(m * n) where q could be O(m + n).

  • I understood the issue of opt being outside the scope. I just didn’t understand the issue of complexity O(M * n), The code you suggested worked.

  • 2

    It’s because for every item of questions, you make a filter in options completely, that is, it will scan the array options n times being n the number of elements of questions. Thus, if questions has m elements, you will have accomplished m * n iterations! It has how to "improve" the code, making this complexity m + n using a dictionary, although this entails an additional memory cost.

2 answers

2


It also has the imperative algorithm that scans the array first options creating a catalog opts whose key is options.question_id and the value is an array of references to the options whose property question_id is the value of the key.

Then the algorithm scans the array question taking on opts the values whose key is question.id

const question = [{
    "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
  }
];

let opts = {};                     //O objeto será o catalogo. 

//Para cada elemento o de options...
for (let o of options) {
  //...verifica se o.question_id já foi catalogado...
  if (o.question_id in opts) {
    opts[o.question_id].push(o);   //...se sim, apenas adiciona o ao catalogo      
  } else {
    opts[o.question_id] = [o];     //...se não, cria uma chave o.question_id e adiciona um array preenchido com o como valor.
  }
}

//Para todos os elementos q de question...
for (let q of question) {
  //...verifica se q.id está no catálogo...
  if (q.id in opts) {
    q.options = opts[q.id];        //...se sim cria em que a propriedade options preenchida com os itens catalogados.
  }
}


console.log(question);

2

The code is very basic, make a map to create a new array and in every passage within the map utilize filter on the other array searching for the information according to the filter and pass the filter information creating a new key options, example:

const questionWithOptions = question.map(x => {
  x.options = options.filter(c => c.question_id === x.id);
  return x;
});

Complete:

const question = [
    {
        "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 questionWithOptions = question.map(x => {
  x.options = options.filter(c => c.question_id === x.id);
  return x;
});

console.log(questionWithOptions);

Browser other questions tagged

You are not signed in. Login or sign up in order to post.