Home > Software design >  How to Push Dynamic Object into an Array from a Loop
How to Push Dynamic Object into an Array from a Loop

Time:10-17

I have an object array with sub-array. I want to push the value of the sum of the sub-array into the main object array.

The sum of sub-array is determined by search array.

Here is the main array with sub-array:

const objectArray = [
  { 'name': 'Alpha', 'data': [{ 'subData': 'a', 'value': 1 }, { 'subData': 'a', 'value': 2 }, { 'subData': 'b', 'value': 3 }, { 'subData': 'b', 'value': 4 }, { 'subData': 'c', 'value': 5 }] },
  { 'name': 'Beta', 'data': [{ 'subData': 'a', 'value': 8 }, { 'subData': 'a', 'value': 9 }, { 'subData': 'b', 'value': 10 }, { 'subData': 'b', 'value': 11 }] }
]

Here is the search array:

   const searchArray = [ { 'search': 'a' }, { 'search': 'b' },{ 'search': 'c' }]

Here is what I have started:

for (let i = 0; i < objectArray.length; i  ) {

   for (let j = 0; j < searchArray.length; j  ) {
     const filterObject = objectArray[i].data.filter(a => a.subData == searchArray[j].search);
     const sumValue = filterObject && filterObject.length > 0 ? filterObject.reduce(function (a, b) { return a    b.value; }, 0) : 0;

     const keyName = searchArray[j].search;

     var objPush = {};
     objPush[keyName] = sumValue;
  
   //  console.log(' obj:', obj );
  
    }
}

Here, the object "objPush" is to be appended to objectArray so that the desired array is this:

const desiredArray = [
  { 'name': 'Alpha', 'a': 3, 'b': 7, 'c':5, 'data': [{ 'subData': 'a', 'value': 1 }, { 'subData': 'a', 'value': 2 }, { 'subData': 'b', 'value': 3 }, { 'subData': 'b', 'value': 4 }, { 'subData': 'c', 'value': 5 }] },
  { 'name': 'Beta', 'a': 17, 'b': 21, 'c':0, 'data': [{ 'subData': 'a', 'value': 8 }, { 'subData': 'a', 'value': 9 }, { 'subData': 'b', 'value': 10 }, { 'subData': 'b', 'value': 11 }] }
]

How do I achieve my desired Array?

CodePudding user response:

You can easily achieve the result using map, forEach, and reduce

const objectArray = [
  {
    name: "Alpha",
    data: [
      { subData: "a", value: 1 },
      { subData: "a", value: 2 },
      { subData: "b", value: 3 },
      { subData: "b", value: 4 },
      { subData: "c", value: 5 },
    ],
  },
  {
    name: "Beta",
    data: [
      { subData: "a", value: 8 },
      { subData: "a", value: 9 },
      { subData: "b", value: 10 },
      { subData: "b", value: 11 },
    ],
  },
];
const searchArray = [{ search: "a" }, { search: "b" }, { search: "c" }];

const result = objectArray.map((obj) => {
  const temp = { ...obj };
  searchArray.forEach(({ search }) => {
    temp[search] = obj.data.reduce((acc, curr) => (curr.subData === search ? acc   curr.value : acc),0);
  });
  return temp;
});

console.log(result);
/* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

const objectArray = [
  {
    name: 'Alpha',
    data: [
      { subData: 'a', value: 1 },
      { subData: 'a', value: 2 },
      { subData: 'b', value: 3 },
      { subData: 'b', value: 4 },
      { subData: 'c', value: 5 },
    ],
  },
  {
    name: 'Beta',
    data: [
      { subData: 'a', value: 8 },
      { subData: 'a', value: 9 },
      { subData: 'b', value: 10 },
      { subData: 'b', value: 11 },
    ],
  },
];

function reduceData(array) {
  return array.reduce((acc, el) => {
    if (acc[el.subData]) {
      acc[el.subData]  = el.value;
    } else {
      acc[el.subData] = el.value || 0;
    }

    return acc;
  }, {});
}

function handleArray(array) {
  return array.map((el) => ({ ...el, ...reduceData(el.data) }))
}

console.log(handleArray(objectArray));
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

It's unclear how you expect to use your searchArray in a more general sense since you're giving them all the same search key and not using it to specifify properties more specifically.

If you just want to aggregate all subData across all objects you can first extract all the unique subData values.

const sub_datum = [...new Set(objectArray.flatMap((o) => o.data.map((d) => d.subData)))];

And then map() over the array and aggregate each object's data array.

const objectArray = [ { name: 'Alpha', data: [ { subData: 'a', value: 1 }, { subData: 'a', value: 2 }, { subData: 'b', value: 3 }, { subData: 'b', value: 4 }, { subData: 'c', value: 5 }, ], }, { name: 'Beta', data: [ { subData: 'a', value: 8 }, { subData: 'a', value: 9 }, { subData: 'b', value: 10 }, { subData: 'b', value: 11 }, ], }, ];

const aggregate_subdata = (arr, data_points) =>
  arr.reduce(
    (a, o) => ((a[o.subData] = a[o.subData]   o.value), a),
    Object.fromEntries(data_points.map((k) => [k, 0]))
  );

const sub_datum = [...new Set(objectArray.flatMap((o) => o.data.map((d) => d.subData)))];

const result = objectArray.map((o) => ({ ...o, ...aggregate_subdata(o.data, sub_datum) }));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related