DEV Community

Julien Dephix
Julien Dephix

Posted on

Calling all beginners: solution to part II's homework

Hello, coders! 💻

In the previous episode of this beginners series I gave you an exercise based on the following initial data:

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

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

Expected result:

const 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

Let's see how we could go about implementing a solution.

Step by step solution

First, let's write in plain English what we need to do:

  1. group purchases by month and items
  2. get first and last item of each month and make them top and flop

Sounds good. Let's write our code outline.

const purchases = [ /* omitted for readability */];
const itemsMonthlyRevenue = getItemsMonthlyRevenue(purchases);
const topFlop = getTopFlopFromMonthlyRevenue(itemsMonthlyRevenue);
Enter fullscreen mode Exit fullscreen mode

getItemsMonthlyRevenue

getItemsMonthlyRevenue needs to add one level compared to what we had in Part II's first exercise to store items' monthly revenue.

const getItemsMonthlyRevenue = (purchases) => {
    let monthlyRevenue = {}
    purchases.forEach(function (purchase) {
        const purchaseDate = purchase.date.substring(0, 7);
        if (monthlyRevenue[purchaseDate] === undefined) {
            monthlyRevenue[purchaseDate] = {}
        }
        monthlyRevenue[purchaseDate][purchase.item] = purchase.amount + (monthlyRevenue[purchaseDate][purchase.item] || 0);
    })

    return monthlyRevenue;
}

const purchases = [ /* omitted for readability */];
const itemsMonthlyRevenue = getItemsMonthlyRevenue(purchases);
console.log(JSON.stringify(itemsMonthlyRevenue, null, 2));
Enter fullscreen mode Exit fullscreen mode

The main difference with Part II's first exercise is that monthlyRevenue[purchaseDate] is now an object so we need to make sure it's initialized before accessing it.

Let's run it and see what we get in the console.

Output:

{
  "2022-05": {
    "socks": 25.98,
    "jacket": 145.98,
    "cap": 12.99
  },
  "2022-06": {
    "socks": 57.980000000000004,
    "cap": 13.99,
    "jacket": 132.99
  },
  "2022-07": {
    "socks": 26.98,
    "jacket": 132.99,
    "cap": 32.99
  }
}
Enter fullscreen mode Exit fullscreen mode

Excellent. Onto getTopFlopFromMonthlyRevenue!


getTopFlopFromMonthlyRevenue

const getTopFlopFromMonthlyRevenue = (monthlyRevenue) => {
    let topFlop = {};
    const NAME_IDX = 0;
    const REVENUE_IDX = 1;
    for (let month in monthlyRevenue) {
        // step 1: get an array of item/monthlyRevenue
        const productsSales = Object.entries(monthlyRevenue[month]);

        // step 2: sort by revenue
        productsSales.sort(function (p1, p2) {
            return p2[REVENUE_IDX] < p1[REVENUE_IDX] ? 1 : -1;
        })

        // step 3: fill the topFlop array object
        topFlop[month] = ({
            flop: productsSales[0][NAME_IDX],
            top: productsSales[productsSales.length - 1][NAME_IDX]
        })
    }

    return topFlop;
}

Enter fullscreen mode Exit fullscreen mode

What's going on here?
Each month holds a list of items as keys and revenue as values and that's what we want to sort.
I make use of Object.entries which returns an array of [key, value] tuples. Example:

console.log(monthlyRevenue['2022-06']);
// outputs
[
  [ "socks", 57.980000000000004 ],
  [ "cap", 13.99 ],
  [ "jacket", 132.99 ],
]
Enter fullscreen mode Exit fullscreen mode

We can now sort that array and get the first and last element which will be out flop and top respectively.

Putting it all together

const getItemsMonthlyRevenue = (purchases) => {
    let monthlyRevenue = {}
    purchases.forEach(function (purchase) {
        const purchaseDate = purchase.date.substring(0, 7);
        if (monthlyRevenue[purchaseDate] === undefined) {
            monthlyRevenue[purchaseDate] = {}
        }
        monthlyRevenue[purchaseDate][purchase.item] = purchase.amount + (monthlyRevenue[purchaseDate][purchase.item] || 0);
    })

    return monthlyRevenue;
}

const getTopFlopFromMonthlyRevenue = (monthlyRevenue) => {
    let topFlop = {};
    const NAME_IDX = 0;
    const REVENUE_IDX = 1;
    for (let month in monthlyRevenue) {
        const productsSales = Object.entries(monthlyRevenue[month]);

        productsSales.sort(function (p1, p2) {
            return p2[REVENUE_IDX] < p1[REVENUE_IDX] ? 1 : -1;
        })

        topFlop[month] = ({
            flop: productsSales[0][NAME_IDX],
            top: productsSales[productsSales.length - 1][NAME_IDX]
        })
    }

    return topFlop;
}


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'},
];
const itemsMonthlyRevenue = getItemsMonthlyRevenue(purchases);
const topFlop = getTopFlopFromMonthlyRevenue(itemsMonthlyRevenue);
console.log(JSON.stringify(topFlop, null, 2));
Enter fullscreen mode Exit fullscreen mode

Hope it helps you, as a beginner, to see how to tackle a task.

Happy coding! ⌨️

Top comments (0)