-1

I have the following data object. Each record contains order value and month of order. My objective here is to count how many orders per month have been ordered.

const data = [{
  order: "a",
  date: "Jan"
}, {
  order: "b",
  date: "Jan"
}, {
  order: "c",
  date: "Feb"
}]

So in the above code in Jan there are two orders, one orders in Feb and no orders for the rest of the months. So for the months which have no orders will have 0 value.

The expected output will be (array format)

orders = [{"Jan":2},
          {"Feb":1},
          {"Mar":0},
          {"Apr":0},
          {"Jun":0},
          {"Jul":0},
          {"Aug":0},
          {"Sept":0},
          {"Oct":0},
          {"Nov":0},
          {"Dec":0}]

Here is the CodeSandbox .

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Teshie Ethiopia
  • 586
  • 8
  • 27
  • 1
    What did you try to solve this yourself? – 0stone0 Sep 12 '22 at 10:39
  • 1
    [Reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) is your friend in this case. – seedBoot Sep 12 '22 at 10:47
  • 1
    this format ain't good, it's basically an array of dictionaries all with just a single entry, and every time you want to use these items you first have to find out what the correct property is. Make it a consistent format, either one object per year `{Jan:2,Feb:1,Mar:0,Apr:0,Jun:0,Jul:0,Aug:0,Sept:0,Oct:0,Nov:0,Dec:0}` or identical objects for each month `[{month:"Jan", count:2},{month:"Feb", count:1},...]` – Thomas Sep 12 '22 at 11:13

3 Answers3

2

You can use a combination of Array.reduce and Array.map to achieve this quite easily, and in a quite readable manner:

const data = [{
  order: "a",
  date: "Jan"
}, {
  order: "b",
  date: "Jan"
}, {
  order: "c",
  date: "Feb"
}]

// A helper array containing all months
const months = ['Jan', 'Feb', 'March'] // ... and so on

// create an object with keys being month name and value being number of orders during that month
const monthsWithOrders = data.reduce((allOrders, currentOrder) => {
  if (allOrders[currentOrder.date]) {
    allOrders[currentOrder.date] += 1
  } else {
    allOrders[currentOrder.date] = 1
  }

  return allOrders
}, {})

// create an array with an oject for each month
const result = months.map(month => {
  return {
    [month]: monthsWithOrders[month] || 0
  }
})

console.log(result)

// results will be:
// [{
//     "Jan": 2
//   },
//   {
//     "Feb": 1
//   },
//   {
//     "March": 0
//   }
// ]
samzmann
  • 2,286
  • 3
  • 20
  • 47
2
  1. Group by the date
  2. map() over each month, set to the grouped value, or 0 as fallback

const data = [{order: "a", date: "Jan"}, {order: "b", date: "Jan"}, {order: "c", date: "Feb"}];

const grouped = data.reduce((p, c) => {
    p[c.date] = (p[c.date] || 0) + 1;
    return p;
}, {})

const result = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]
  .map(m => ({ [m]: grouped[m] || 0 }));

console.log(result);

Result:

[
  {
    "Jan": 2
  },
  {
    "Feb": 1
  },
  {
    "Mar": 0
  },
  {
    "Apr": 0
  },
  {
    "May": 0
  },
  {
    "Jun": 0
  },
  {
    "Jul": 0
  },
  {
    "Aug": 0
  },
  {
    "Sep": 0
  },
  {
    "Oct": 0
  },
  {
    "Nov": 0
  },
  {
    "Dec": 0
  }
]
0stone0
  • 34,288
  • 4
  • 39
  • 64
0

forEach and filter is enough for us to make this array object. Also, we can make it with using reduce.

   const data= [{
    order: "a",
    date: "Jan"
  }, {
    order: "b",
    date: "Jan"
  }, {
    order: "c",
    date: "Feb"
  }]
  const weeks = ["Feb", "Jan", "May"]
  const newArray= []
  weeks.forEach((element) => {
    let obj = {}
    const lengtOfData = data.filter(eachData=> element == eachData.date)
    obj[element] = lengtOfData.length
    newArray.push(obj)
  })
Onur Doğan
  • 346
  • 2
  • 8