Home > other >  Javascript grouping
Javascript grouping

Time:12-16

  • How can I add data by grouping with country label and create data array that has 12 index indicating months and containing value of data before grouping. I need help, how to push and group the data according to the month number. e.x
arr = [
  { label: 'US', data: '10', monthNumber: 1 },
  { label: 'US', data: '2', monthNumber: 3  },
  { label: 'US', data: '60', monthNumber: 2  },
  { label: 'UK', data: '10', monthNumber: 5 },
  { label: 'SA', data: '1', monthNumber: 1  },
  { label: 'CA', data: '70', monthNumber: 1  },
  { label: 'SA', data: '10', monthNumber: 12 },
];

now i need the results to be like

[
  { label: 'US', data: [10,60,2,0,0,0,0,0,0,0,0,0] },
  { label: 'UK', data: [0,0,0,0,10,0,0,0,0,0,0,0] },
  { label: 'SA', data: [1,0,0,0,0,0,0,0,0,0,0,10] },
  { label: 'CA', data: [70,0,0,0,0,0,0,0,0,0,0,0] },
];

CodePudding user response:

Create a new object by reducing over the array using the labels as object keys, and initialising the property value as an object with a label, and a pre-filled array of zeros. Then update the array with the data at the relevant position.

const arr=[{label:"US",data:"10",monthNumber:1},{label:"US",data:"2",monthNumber:3},{label:"US",data:"60",monthNumber:2},{label:"UK",data:"10",monthNumber:5},{label:"SA",data:"1",monthNumber:1},{label:"CA",data:"70",monthNumber:1},{label:"SA",data:"10",monthNumber:12}];

function grouper(arr) {

  // `reduce` over the array passing in an
  // empty object as the initial accumulator value
  const out = arr.reduce((acc, c) => {

    // Destructure the properties from the current
    // iterated object
    const { label, data, monthNumber } = c;

    // If the label doesn't exist as a key on the object
    // create it, and assign an object as its value, using
    // the label, and adding a pre-filled array of zeros to
    // its data property
    acc[label] ??= { label, data: new Array(12).fill(0) };

    // Update the data array with the data value at the
    // appropriate position
    acc[label].data[monthNumber - 1] = Number(data);

    // Return the accumulator for the next iteration
    return acc;

  }, {});

  // Finally get the array of updated objects
  // from the accumulated data
  return Object.values(out);
  
}

console.log(grouper(arr));

Additional documentation

CodePudding user response:

For grouping, you could make use of reduce

const arr = [
  { label: "US", data: "10", monthNumber: 1 },
  { label: "US", data: "2", monthNumber: 3 },
  { label: "US", data: "60", monthNumber: 2 },
  { label: "UK", data: "10", monthNumber: 5 },
  { label: "SA", data: "1", monthNumber: 1 },
  { label: "CA", data: "70", monthNumber: 1 },
  { label: "SA", data: "10", monthNumber: 12 },
]

let res = arr.reduce((acc, { label, monthNumber, data }) => {
  if (!acc[label]) acc[label] = Array(12).fill(0)
  acc[label][monthNumber - 1] = Number(data)
  return acc
}, {})

res = Object.entries(res).map(([label, data]) => ({ label, data }))

console.log(res)

CodePudding user response:

  • First I have extracted the label from the current array.
  • After that, I have a loop through those labels, and inside that loop through the array, and created an object with store values of data and label.
  • please see the comments for a better understanding.

Important thing to notice here is that for the same month number for labels value will be replaced with the last one.

arr = [{
    label: 'US',
    data: '10',
    monthNumber: 1
  },
  {
    label: 'US',
    data: '2',
    monthNumber: 3
  },
  {
    label: 'US',
    data: '60',
    monthNumber: 2
  },
  {
    label: 'UK',
    data: '10',
    monthNumber: 5
  },
  {
    label: 'SA',
    data: '1',
    monthNumber: 1
  },
  {
    label: 'CA',
    data: '70',
    monthNumber: 1
  },
  {
    label: 'SA',
    data: '10',
    monthNumber: 12
  },
];
const labels = [];

const result = [];
// extracting unique labels
arr.forEach(item => {
  !labels.includes(item.label) && labels.push(item.label);
})

// looping through labels
labels.forEach(label => {
  // creating empty object
  const object = {};
  // creating data array with 12 values by default 0
  const data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
  // loop though array values
  arr.forEach(item => {
    // checking if current outer label is matching with array label 
    if (item.label == label) {
      // if abive condition true add label key in object with value of current outer label 
      object["label"] = label;
      // updating month value 
      data[item.monthNumber - 1] = item.data;
    }
    // adding data in object with key data.
    object["data"] = data;
  })
  // pushing final object in result
  result.push(object);
})
//printing final result
console.log(result);

CodePudding user response:

Good starting point will be to group the data by label first.

Then take the values from that to remap the data.

Create a Month array generating a new array with 0 values

Loop through and add the data to the month array based on MonthNumber

const remap = () => {
  let arr = [
    { label: 'US', data: '10', monthNumber: 1 },
    { label: 'US', data: '2', monthNumber: 3 },
    { label: 'US', data: '60', monthNumber: 2 },
    { label: 'UK', data: '10', monthNumber: 5 },
    { label: 'SA', data: '1', monthNumber: 1 },
    { label: 'CA', data: '70', monthNumber: 1 },
    { label: 'SA', data: '10', monthNumber: 12 }
  ];

  return Object.values(
    arr.reduce((acc, v) => {
      if (!acc.hasOwnProperty(v.label)) {
        acc[v.label] = [];
      }
      acc[v.label].push(v);
      return acc;
    }, {})
  ).map((flatData) => {
    const label = Array.isArray(flatData) && flatData.length > 0 ? flatData[0].label : '';
    const monthArray = new Array(12).fill(0);
    flatData.forEach(({ data, monthNumber }) => {
      monthArray[monthNumber] = parseInt(data);
    });
    return { label, data: monthArray };
  });
};

console.log(remap())

CodePudding user response:

Try this solution:


function setupGraph(arr){
    data = [];
    for (let i = 0; i < arr.length; i  ) {
        let found = false;
        for (let j = 0; j < data.length; j  ) {
            if (data[j].label === arr[i].label) {
                data[j].data[arr[i].monthNumber - 1] = Number(arr[i].data);
                found = true;
                break;
            }
        }
        if (!found) {
            data.push({ label: arr[i].label, data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] });
            data[data.length - 1].data[arr[i].monthNumber - 1] = Number(arr[i].data);
        }
    }
    return data;
    
}

Testing the function:


arr = [
    { label: 'US', data: '10', monthNumber: 1 },
    { label: 'US', data: '2', monthNumber: 3  },
    { label: 'US', data: '60', monthNumber: 2  },
    { label: 'UK', data: '10', monthNumber: 5 },
    { label: 'SA', data: '1', monthNumber: 1  },
    { label: 'CA', data: '70', monthNumber: 1  },
    { label: 'SA', data: '10', monthNumber: 12 },
];
let result = setupGraph(arr)
console.log(result);


[
  {
    label: 'US',
    data: [
      10, 60, 2, 0, 0,
       0,  0, 0, 0, 0,
       0,  0
    ]
  },
  {
    label: 'UK',
    data: [
      0, 0, 0, 0, 10,
      0, 0, 0, 0,  0,
      0, 0
    ]
  },
  {
    label: 'SA',
    data: [
      1,  0, 0, 0, 0,
      0,  0, 0, 0, 0,
      0, 10
    ]
  },
  {
    label: 'CA',
    data: [
      70, 0, 0, 0, 0,
       0, 0, 0, 0, 0,
       0, 0
    ]
  }
]

  • Related