DEV Community

Cover image for Calling all beginners - part II: Return Of The Arrays!
Julien Dephix
Julien Dephix

Posted on • Edited on

Calling all beginners - part II: Return Of The Arrays!

Cover photo by Faris Mohammed


Hello, coders! 💻

In this second post aimed at beginners we'll continue manipulating arrays because:

  1. arrays are fun
  2. you will have to deal with arrays A LOT in your career so you might as well feel comfortable working with them

Context

You're given a list of purchases customers have made over the past few months. Given the quantity it's fair to say it's not a very popular shop...

const purchases = [
    {item: 'socks', amount: 25.98, date: '2022-05-07 09:31:29'},
    {item: 'jacket', amount: 145.98, date: '2022-05-17 17:01:09'},
    {item: 'cap', amount: 12.99, date: '2022-05-17 17:03:12'},
    {item: 'socks', amount: 43.99, date: '2022-06-11 18:24:16'},
    {item: 'cap', amount: 13.99, date: '2022-06-11 18:24:16'},
    {item: 'jacket', amount: 132.99, date: '2022-06-21 11:21:35'},
    {item: 'socks', amount: 13.99, date: '2022-06-23 09:43:28'},
    {item: 'socks', amount: 12.99, date: '2022-07-01 13:14:56'},
    {item: 'jacket', amount: 132.99, date: '2022-07-03 15:24:24'},
    {item: 'cap', amount: 32.99, date: '2022-07-05 11:14:15'},
    {item: 'socks', amount: 13.99, date: '2022-07-07 11:14:15'},
];
Enter fullscreen mode Exit fullscreen mode

Exercise 1

Your task is to compute the total amount of purchases per month and store that in an object named monthlyRevenue.

Expected object

⚠️ Amounts have 2 decimal places.

let monthlyRevenue = {
  '2022-05': 184.95,
  '2022-06': 204.96,
  '2022-07': 192.96
}
Enter fullscreen mode Exit fullscreen mode

Solution to exercise 1

👇

Click for a step by step guide

Let's see how we can break down what we need to do.

  1. loop through purchases
  2. for each purchase we need to do some sort of date manipulation to get the year/month part
  3. then we add the amount to monthlyRevenue for the date found in our previous step.
  4. then we'll see what's left to do.

Sounds good. Let's code! ⌨️

// purchases omitted for readability
let monthlyRevenue = {}
// first step: loop!
purchases.forEach(function (purchase) {
    // do something
})
Enter fullscreen mode Exit fullscreen mode

Easy.
Now, how do we get the year/month part from each purchase.date?
Well, purchase.date is a string and the 7 first characters are year and month which is what we need.
So how about using substring?

purchase.date.substring(0, 7)
Enter fullscreen mode Exit fullscreen mode

Let's try the following:

// purchases omitted for readability
let monthlyRevenue = {}
// first step: loop!
purchases.forEach(function (purchase) {
    // second step: year/month part
    const purchaseDate = purchase.date.substring(0, 7);
    console.log(purchaseDate);
})
Enter fullscreen mode Exit fullscreen mode

which outputs:

2022-05
2022-05
2022-05
2022-06
2022-06
2022-06
2022-06
2022-07
2022-07
2022-07
2022-07
Enter fullscreen mode Exit fullscreen mode

All good!

Onto step 3: sum of amounts.

Now that we have the year/month part we can store amounts in monthlyRevenue[purchaseDate].

Let's see what happens when we innocently add each purchase.amount to monthlyRevenue[purchaseDate] to get a sum.

// purchases omitted for readability
let monthlyRevenue = {}
// first step: loop!
purchases.forEach(function (purchase) {
    // second step: year/month part
    const purchaseDate = purchase.date.substring(0, 7);
    // step 3: sum
    monthlyRevenue[purchaseDate] += purchase.amount;
})
console.log(monthlyRevenue);
Enter fullscreen mode Exit fullscreen mode

outputs:

Object {
  "2022-05": NaN,
  "2022-06": NaN,
  "2022-07": NaN
}
Enter fullscreen mode Exit fullscreen mode

Ouch! NaN? 🍞?
It means Not a Number and is due to the fact that we're trying to add a number to monthlyRevenue[purchaseDate] which is initially undefined.
We need to make sure it's 0 before adding anything to it.

monthlyRevenue[purchaseDate] = purchase.amount + (monthlyRevenue[purchaseDate] || 0);
Enter fullscreen mode Exit fullscreen mode

should do the trick!
|| return the rightmost element if the first one is falsy.
So when we first access monthlyRevenue[purchaseDate] it will return undefined which is falsy so || returns 0.
From now on monthlyRevenue[purchaseDate] will no longer be falsy.

Let's update our code:

// purchases omitted for readability
let monthlyRevenue = {}
// first step: loop!
purchases.forEach(function (purchase) {
    // second step: year/month part
    const purchaseDate = purchase.date.substring(0, 7);
    // step 3: sum
    monthlyRevenue[purchaseDate] = purchase.amount + (monthlyRevenue[purchaseDate] || 0);
})
console.log(monthlyRevenue);
Enter fullscreen mode Exit fullscreen mode

and see the output:

Object {
  "2022-05": 184.95,
  "2022-06": 204.96000000000004,
  "2022-07": 192.96000000000004
}
Enter fullscreen mode Exit fullscreen mode

Hooray! 🚀

Wait, Why so many decimal places?! It has to do with floating points. It's a topic in its own right and I won't go into details here. What I can tell you though, is that there we're not done yet!

Looking back at the exercise's description I see a ⚠️ sign to let us know numbers must have 2 decimal places.

And that's step 4 which I mentioned earlier. ^^

Let's round things after the loop that populates monthlyRevenue. We'll use toFixed:

// step 4: rounding numbers
for (let yearMonth in monthlyRevenue) {
    monthlyRevenue[yearMonth] = monthlyRevenue[yearMonth].toFixed(2);
}
console.log(monthlyRevenue);
Enter fullscreen mode Exit fullscreen mode

which outputs

Object {
  "2022-05": "184.95",
  "2022-06": "204.96",
  "2022-07": "192.96"
}
Enter fullscreen mode Exit fullscreen mode

Almost there! toFixed returns a string and we want a number so we call Number to parse strings and voilà:

// step 4: rounding numbers
for (let yearMonth in monthlyRevenue) {
    monthlyRevenue[yearMonth] = Number(monthlyRevenue[yearMonth].toFixed(2));
}
console.log(monthlyRevenue);
Enter fullscreen mode Exit fullscreen mode

What does the output look like?

Object {
  "2022-05": 184.95,
  "2022-06": 204.96,
  "2022-07": 192.96
}
Enter fullscreen mode Exit fullscreen mode

🚀 Now we're talking. It outputs exactly what was asked.

Putting it all together

Here's all the code:

const purchases = [
    {item: 'socks', amount: 25.98, date: '2022-05-07 09:31:29'},
    {item: 'jacket', amount: 145.98, date: '2022-05-17 17:01:09'},
    {item: 'cap', amount: 12.99, date: '2022-05-17 17:03:12'},
    {item: 'socks', amount: 43.99, date: '2022-06-11 18:24:16'},
    {item: 'cap', amount: 13.99, date: '2022-06-11 18:24:16'},
    {item: 'jacket', amount: 132.99, date: '2022-06-21 11:21:35'},
    {item: 'socks', amount: 13.99, date: '2022-06-23 09:43:28'},
    {item: 'socks', amount: 12.99, date: '2022-07-01 13:14:56'},
    {item: 'jacket', amount: 132.99, date: '2022-07-03 15:24:24'},
    {item: 'cap', amount: 32.99, date: '2022-07-05 11:14:15'},
    {item: 'socks', amount: 13.99, date: '2022-07-07 11:14:15'},
];

let monthlyRevenue = {}
// first step: loop!
purchases.forEach(function (purchase) {
    // second step: year/month part
    const purchaseDate = purchase.date.substring(0, 7);
    // step 3: sum
    monthlyRevenue[purchaseDate] = purchase.amount + (monthlyRevenue[purchaseDate] || 0);
})
// step 4: rounding numbers
for (let yearMonth in monthlyRevenue) {
    monthlyRevenue[yearMonth] = Number(monthlyRevenue[yearMonth].toFixed(2));
}
console.log(monthlyRevenue);
Enter fullscreen mode Exit fullscreen mode

😅 That was a long ass guide!

Too long? Too detailed? Let me know in the comments! 💬


Homework 🏡

Now that arrays and objects have no secrets for you, here's your assignment.

Create a list of best and worst selling items of each month.
Best and worst are defined by the revenue they generated.

Expected result:

let topFlops = {
  "2022-05": {
    top: 'jacket',
    flop: 'cap'
  },
  "2022-06": {
    top: 'jacket',
    flop: 'cap'
  },
  "2022-07": {
    top: 'jacket',
    flop: 'socks'
  }
}
Enter fullscreen mode Exit fullscreen mode

Happy coding! 💻

Top comments (0)