skip to Main Content

I have array of object whose element contains an array property. I need to reduce the array to shorter one based the label value and merge and replace _data array to new one like this below:

const originalArray = [
    {  label: "approved", data: [1, 0, 0, 0, 0, 0, 0] },
    {  label: "approved", data: [0, 2, 0, 0, 0, 0, 0] },
    {  label: "rejected", data: [0, 0, 3, 0, 0, 0, 0] },
    {  label: "rejected", data: [0, 0, 0, 1, 0, 0, 0] },
    {  label: "pending", data: [0, 1, 0, 0, 0, 0, 0] },
    {  label: "pending", data: [0, 0, 0, 0, 0, 7, 0] }
];
const expectedArray = [
    {  label: "approved", data: [1, 2, 0, 0, 0, 0, 0] },
    {  label: "rejected", data: [0, 0, 3, 1, 0, 0, 0] },
    {  label: "pending", data: [0, 1, 0, 0, 0, 7, 0] },
    
]

I tried to merge the data property of each element by label and then create a unique array from it

3

Answers


  1. You could do this using reduce but it’s perhaps slightly more straightforward to just accumulate the values for each label into an object, then unpack it into your desired array form:

    const originalArray = [
        {  label: "approved", data: [1, 0, 0, 0, 0, 0, 0] },
        {  label: "approved", data: [0, 2, 0, 0, 0, 0, 0] },
        {  label: "rejected", data: [0, 0, 3, 0, 0, 0, 0] },
        {  label: "rejected", data: [0, 0, 0, 1, 0, 0, 0] },
        {  label: "pending", data: [0, 1, 0, 0, 0, 0, 0] },
        {  label: "pending", data: [0, 0, 0, 0, 0, 7, 0] }
    ];
    
    function combine(input) {
        // Helper function to add two arrays element-by-element
        const addArrays = (a, b) => a ? a.map((_,i) => a[i] + b[i]) : b;
    
        // Accumulate arrays into an object keyed by label
        const perLabel = {};
        for (const { label, data } of input)
            perLabel[label] = addArrays(perLabel[label], data);
    
        // Convert the entries in the object into the expected array shape
        return Object.entries(perLabel).map(([label, data]) => ({ label, data }));
    }
    
    const combined = combine(originalArray);
    console.log(combined);
    Login or Signup to reply.
  2. You can first aggregate the arrays by label into a map, then merge them.

    const originalArray = [
      { label: 'approved', data: [1, 0, 0, 0, 0, 0, 0] },
      { label: 'approved', data: [0, 2, 0, 0, 0, 0, 0] },
      { label: 'rejected', data: [0, 0, 3, 0, 0, 0, 0] },
      { label: 'rejected', data: [0, 0, 0, 1, 0, 0, 0] },
      { label: 'pending', data: [0, 1, 0, 0, 0, 0, 0] },
      { label: 'pending', data: [0, 0, 0, 0, 0, 7, 0] },
    ];
    
    const map = new Map();
    for (const o of originalArray) {
      const dataArrs = map.get(o.label) || [];
      map.set(o.label, [...dataArrs, o.data]);
    }
    
    const result = [];
    for (const [label, dataArrs] of map.entries()) {
      const data = dataArrs[0];
      for (let i = 1; i < dataArrs.length; i++) {
        for (let j = 0; j < dataArrs[i].length; j++) {
          data[j] += dataArrs[i][j];
        }
      }
      result.push({ label, data });
    }
    
    console.log(
      'result:',
      JSON.stringify(result, (k, v) => (k === 'data' ? v.toString() : v), 2)
    );
    div.as-console-wrapper {
      max-height: 200px;
    }
    Login or Signup to reply.
  3. const originalArray = [
      { label: "approved", data: [1, 0, 0, 0, 0, 0, 0] },
      { label: "approved", data: [0, 2, 0, 0, 0, 0, 0] },
      { label: "rejected", data: [0, 0, 3, 0, 0, 0, 0] },
      { label: "rejected", data: [0, 0, 0, 1, 0, 0, 0] },
      { label: "pending", data: [0, 1, 0, 0, 0, 0, 0] },
      { label: "pending", data: [0, 0, 0, 0, 0, 7, 0] }
    ];
    
    const expectedArray = Object.values(originalArray.reduce((acc, curr) => {
      if (acc[curr.label]) {
        acc[curr.label].data = acc[curr.label].data.map((val, i) => val + curr.data[i]);
      } else {
        acc[curr.label] = {
          label: curr.label,
          data: [...curr.data]
        };
      }
      return acc;
    }, {}));
    
    console.log(expectedArray);

    Use Array.prototype.reduce() to accumulate an object where each key is unique to label, for each loop if the label already exists in the accumulator object, then add data array with the accumulator’s data (corresponding values). If the object with the label does not exist then a new object is created with the corresponding label as key.

    We then just take values array from the accumulated object using Object.values().

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search