1

I have an array with several objects some have the same keys (Question and QuestionId), for example:

    var jsonData = [
            {
                Question: "Was the training useful?",
                QuestionId: 1,
                myData: [{ name: 'No', value: 1 }] },
            {
                Question: "Was the training useful?",
                QuestionId: 1 ,
                myData: [{ name: 'Yes', value: 1 }]
        }];

How can I combine these objects into one, expected output:

      var jsonData = [
        {
            Question: "Was the training useful?",
            QuestionId: 1,
            myData: [{ name: 'No', value: 1 },
                     { name: 'Yes', value: 1 }] 
          }];
hncl
  • 2,295
  • 7
  • 63
  • 129
  • could initialize a new array, and loop through all your data, looking to see if there's already an instance of your two key value pairs, and if so, add the `myData` value to the entry in your new array. – async await Apr 12 '22 at 22:09

3 Answers3

2

var jsonData = [{
    Question: "Was the training useful?",
    QuestionId: 1,
    myData: [{
      name: 'No',
      value: 1
    }]
  },
  {
    Question: "Was the training useful?",
    QuestionId: 1,
    myData: [{
      name: 'Yes',
      value: 1
    }]
  }
];

const result = Object.values(jsonData.reduce((acc, obj) => {
  if (!acc[obj.QuestionId]) {
    acc[obj.QuestionId] = obj;
  } else {
    acc[obj.QuestionId].myData = acc[obj.QuestionId].myData ?? []; // if myData is null or undefined, set it to an empty array
    acc[obj.QuestionId].myData = acc[obj.QuestionId].myData.concat(obj.myData);
  }
  return acc;
}, {}));

console.log(result);
HellaMad
  • 5,294
  • 6
  • 31
  • 53
  • That is great thank you. However, it returned two objects, the first is the merged myData, and the second object with the Yes answer, I was hoping to return only one object. – hncl Apr 12 '22 at 22:28
  • 1
    @hncl see the snippet, it's working as you expected – pilchard Apr 12 '22 at 22:31
  • @hncl not sure what you mean, can you share the output? – HellaMad Apr 12 '22 at 22:35
  • @HellaMad, it is working now as expected. I have accepted your answer, thanks – hncl Apr 12 '22 at 22:38
  • @pilchard, thank you; my challenge is the array is generated using Ajax. I get this error: acc[obj.QuestionId].myData.concat is not a function. I tried to run the script as a function on Ajax complete, still get the same error. Any suggestions? – hncl Apr 13 '22 at 01:21
  • @hncl I'm assuming myData might be null or undefined. If that's the case, see the updated answer. – HellaMad Apr 13 '22 at 02:03
  • @HellaMad, thank you. I still get this error: acc[obj.QuestionId].myData.concat is not a function. I have posted another question @ https://stackoverflow.com/questions/71850916/javascript-merge-ajax-array-objects-with-the-same-keys?noredirect=1#comment126969361_71850916 – hncl Apr 13 '22 at 02:09
0
function mergeData(data) {
  const acc = {}
  data.forEach(x => {
    const id = x.QuestionId
    if (!acc[id]) acc[id] = x
    else acc[id].myData = acc[id].myData.concat(x.myData)
  })
  return Object.values(acc)
}
Sereyn
  • 195
  • 12
0

You can use forEach to create an object where the keys are the question IDs and then use Object.values to get the values into an array.

var jsonData = [{
  Question: "Was the training useful?",
  QuestionId: 1,
  myData: [{ name: 'No', value: 1 }] 
}, {
  Question: "Was the training useful?",
  QuestionId: 1 ,
  myData: [{ name: 'Yes', value: 1 }]
}];

var temp = {};
jsonData.forEach(x=>{
  if(!temp[x.QuestionId]) {temp[x.QuestionId] = x;} 
  else {temp[x.QuestionId].myData.push(x.myData);}
});

var arr = Object.values(temp);

console.log(arr);
Chris Strickland
  • 3,388
  • 1
  • 16
  • 18