-1

I have an array of objects like so

 [
{_id: "5ca8b8ca0f1b2f54646ded9a", question: "Do you like it?", answer: "yes"},
{_id: "5ca8b8ca0f1b2f54646ded99", question: "Do you like it?", answer: "no"},
{_id: "5ca8b8f80f1b2f54646deda1", question: "Where are you?", answer: "home"},
{_id: "5ca8b8f80f1b2f54646deda0", question: "Where are you?", answer: "home"}
]

and I want it to be reproduced like the following:

[
 {
  "question": "Do you like it?",
  "answers": [{"answer": "yes", "count": 1}, {"answer": "no", "count": 1}]
 },
 {
  "question": "Where are you?",
  "answers": [{"answer": "home", "count": 2}]
 }
]

I have tried to solve this but i couldn't so any help would be much appreciated. Thank you

Teknotica
  • 1,096
  • 6
  • 19
hamdi islam
  • 1,327
  • 14
  • 26
  • Possible duplicate of [Remove duplicates from an array of objects in JavaScript](https://stackoverflow.com/questions/2218999/remove-duplicates-from-an-array-of-objects-in-javascript) – chazsolo Apr 07 '19 at 11:16

2 Answers2

1

We can use Array.find to find the question-answer pair then add a new question-answer pair object if the pair is not existing or update the existing question-answer pair object.

If the question exits but the answer doesn't then simply add the new answer in the answers array.

If both the question and answer exists then increment the answer count property by 1.

If the question itself is missing then add a new object with the question property and answers property and set the count to 1.

Then finally use Array.reduce to accumulate the objects into an array.

const data = [
{_id: "5ca8b8ca0f1b2f54646ded9a", question: "Do you like it ?", answer: "yes"},
{_id: "5ca8b8ca0f1b2f54646ded99", question: "Do you like it ?", answer: "no"},
{_id: "5ca8b8f80f1b2f54646deda1", question: "Where are you ?", answer: "home"},
{_id: "5ca8b8f80f1b2f54646deda0", question: "Where are you ?", answer: "home"}
];

const res = data.reduce((acc, {question, answer}) => {
 qFound = acc.find(qa => qa.question === question);
 if(qFound){ 
   ansFound = qFound.answers.find(ans => ans.answer === answer);
   if(ansFound){
      ansFound.count = ansFound.count + 1;
   }else{
      qFound.answers.push({answer, count:1});
   }
 }else{
   acc.push({
     question,
     answers: [].concat({answer, count: 1})
  });
 }
 return acc;
},[]);
console.log(res);
   
Fullstack Guy
  • 16,368
  • 3
  • 29
  • 44
0

use reduce to create objects grouped by question and answer values and then later to discard the keys use Object.values()

const input =  [
  {_id: "5ca8b8ca0f1b2f54646ded9a", question: "Do you like it ?", answer: "yes"},
  {_id: "5ca8b8ca0f1b2f54646ded99", question: "Do you like it ?", answer: "no"},
  {_id: "5ca8b8f80f1b2f54646deda1", question: "Where are you ?", answer: "home"},
  {_id: "5ca8b8f80f1b2f54646deda0", question: "Where are you ?", answer: "home"}
];

const groupByQuestionAndAnswers = Object.values(input.reduce((accu, {question, answer}) => {
  if(!accu[question]) 
    accu[question] = {question};
  if(!accu[question][answer]) 
    accu[question][answer] = {answer, count: 0};
  accu[question][answer].count += 1;

  return accu;
}, {}));

const output = groupByQuestionAndAnswers.map(({question, ...res}) => {
  return {question, answers: Object.values(res)};
});

console.log(output);
random
  • 7,756
  • 3
  • 19
  • 25