Home > Mobile >  JavaScript merge (AJAX) array objects with the same keys
JavaScript merge (AJAX) array objects with the same keys

Time:04-13

My application is MVC 5, I am using the following Ajax to generate an array:

$.ajax({
            type: "Post",
            url: '@Url.Action("Getthereport", "Surveys")',
            async: false,
            cache: false,
            dataType: "json",
            data: { 'test': "All" },
            success: function (result) {

                if (result && result.Grid.length > 0) {
                    for (let i = 0; i < result.Grid.length; i  ) {
                        jsonData.push({
                            Question: result.Grid[i].Body,
                            QuestionId: result.Grid[i].QuestionId,
                            myData: { name: result.Grid[i].name, value: result.Grid[i].value }
                          });
                    };
                }
               },
            complete: function () {
               reduce();
            },
            error: function(err) {
                alert(err.status   " : "   err.statusText);
            }
        });

I generates the following:

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

to merge the objects, I use:

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.concat(obj.myData);
  }
  return acc;

Works great if the array is hardcoded and generates:

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

However, if the array is generated by Ajax call, I get the following error:

 acc[obj.QuestionId].myData.concat is not a function

I tried to run the reduce script on Ajax complete and directly both did not work.

CodePudding user response:

In the success property of your ajax call options you're pushing myData as an object, not as an array

  success: function (result) {

    if (result && result.Grid.length > 0) {
      for (let i = 0; i < result.Grid.length; i  ) {
        jsonData.push({
          Question: result.Grid[i].Body,
          QuestionId: result.Grid[i].QuestionId,
          myData: { name: result.Grid[i].name, value: result.Grid[i].value }
        });
      };
    }
  },

Which means that the output is not as you stated but rather

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

You can either declare it as an array at that stage to generate the output you originally posted,

      for (let i = 0; i < result.Grid.length; i  ) {
        jsonData.push({
          ...
          myData: [{ name: result.Grid[i].name, value: result.Grid[i].value }]
        });
      };

or adjust your reduce.

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) => {
  acc[obj.QuestionId] ??= { ...obj, myData: [] };
  acc[obj.QuestionId].myData.push(obj.myData);
  return acc;
}, {}));

console.log(JSON.stringify(result, null, 2))

  • Related