skip to Main Content

I have the below data object that contains information about products, customers & purchases .

const data = {
  products: [
    {
      id: "p01",
      name: "Bike Insurance",
    },
    {
      id: "p02",
      name: "Car Insurance",
    },
    {
      id: "p03",
      name: "Home Insurance",
    },
    {
      id: "p04",
      name: "Pet Insurance",
    },
  ],
  customers: [
    { id: "c01", firstname: "Rachel", lastname: "Jane" },
    { id: "c02", firstname: "Leilah", lastname: "Mandi" },
    { id: "c03", firstname: "Campbell", lastname: "Kendall" },
    { id: "c04", firstname: "Madonna", lastname: "Sammie" },
  ],
  purchases: [
    {
      customerId: "c01",
      purchases: [
        {
          productId: "p02",
          purchasedAt: "2021-08-03T00:00:00.000Z",
        },
        {
          productId: "p02",
          purchasedAt: "2021-08-04T00:00:00.000Z",
        },
        {
          productId: "p01",
          purchasedAt: "2021-09-12T00:00:00.000Z",
        },
        {
          productId: "p01",
          purchasedAt: "2021-09-12T00:00:00.000Z",
        },
      ],
    },
    {
      customerId: "c03",
      purchases: [
        {
          productId: "p04",
          purchasedAt: "2021-08-03T00:00:00.000Z",
        },
        {
          productId: "p04",
          purchasedAt: "2021-09-12T00:00:00.000Z",
        },
        {
          productId: "p03",
          purchasedAt: "2021-09-12T00:00:00.000Z",
        },
        {
          productId: "p01",
          purchasedAt: "2021-09-12T00:00:00.000Z",
        },
      ],
    },
    {
      customerId: "c02",
      purchases: [
        {
          productId: "p01",
          purchasedAt: "2021-09-12T00:00:00.000Z",
        },
      ],
    },
  ],
};

I have so far filtered out the customers who have made purchases by using the following code:

const customersWhoPurchased = data["customers"].filter((c) =>
  data["purchases"].find((p) => p.customerId === c.id)
)

so the customersWhoPurchased now looks like this:

[ { id: 'c01', firstname: 'Rachel', lastname: 'Jane' },
  { id: 'c02', firstname: 'Leilah', lastname: 'Mandi' },
  { id: 'c03', firstname: 'Campbell', lastname: 'Kendall' } ]

What I would like to achieve now; is going through the purchases for each customer in the data object, checking productId in the purchases.purchases array and matching that up to the products and then returning the name of each product the customer has purchased and adding them into an additional key value pair in the customersWhoPurchased array, with the value being an array of each product name. So the end result would look like this.

customers: [
  { id: "c01", firstname: "Rachel", lastname: "Jane", productNames: ['Bike Insurance', 'Car Insurance'] },
  { id: "c02", firstname: "Leilah", lastname: "Mandi", productNames: ['Bike Insurance'] },
  { id: "c03", firstname: "Campbell", lastname: "Kendall", productNames: ['Bike Insurance', 'Home Insurance', 'Pet Insurance'] },
],

Hopefully it makes sense with regards to what I am trying to achieve here.

What would be awesome; is not only the solution but an explanation/theory as to how you solved the problem. I’m really trying to improve on problem solving with regards to complex objects, so any help here would go a long way.

2

Answers


  1. First, I would create a hashtable-like structure for easy access:

    const productsObj = data["products"].reduce((obj, item) => {
        obj[item.id] = item;
        return obj
    },{});
    // {"p01":{"id":"p01","name":"Bike Insurance"},"p02":{"id":"p02","name":"Car Insurance"},"p03":{"id":"p03","name":"Home Insurance"},"p04":{"id":"p04","name":"Pet Insurance"}}
    
    const customersObj = data["customers"].reduce((obj, item) => {
        obj[item.id] = item;
        return obj
    },{});
    // {"c01":{"id":"c01","firstname":"Rachel","lastname":"Jane"},"c02":{"id":"c02","firstname":"Leilah","lastname":"Mandi"},"c03":{"id":"c03","firstname":"Campbell","lastname":"Kendall"},"c04":{"id":"c04","firstname":"Madonna","lastname":"Sammie"}}
    

    Then, I would do something like this with the purchases, using the customer id as the key instead.

    Consider that I am grouping purchases by the customer.

    const purchasesGroupedByUser = data["purchases"].reduce((obj, item) => {
        // if first time finding this user
        if (!obj.hasOwnProperty(item.customerId)) {
            obj[item.customerId] = customersObj[item.customerId];
            obj[item.customerId].productNames = [];
        }
    
        const productNamesInCurrentPurchase = item.purchases.map(
            (product) => productsObj[product.productId].name
        );
    
        // updating productNames
        obj[item.customerId].productNames = obj[
            item.customerId
        ].productNames.concat(productNamesInCurrentPurchase);
    
        return obj;
    }, {});
    // {"c01":{"id":"c01","firstname":"Rachel","lastname":"Jane","productNames":["Car Insurance","Car Insurance","Bike Insurance","Bike Insurance"]},"c03":{"id":"c03","firstname":"Campbell","lastname":"Kendall","productNames":["Pet Insurance","Pet Insurance","Home Insurance","Bike Insurance"]},"c02":{"id":"c02","firstname":"Leilah","lastname":"Mandi","productNames":["Bike Insurance"]}}
    

    And finally, convert to array:

    const customersWithProductNames = Object.values(purchasesGroupedByUser);
    // [{"id":"c01","firstname":"Rachel","lastname":"Jane","productNames":["Car Insurance","Car Insurance","Bike Insurance","Bike Insurance"]},{"id":"c03","firstname":"Campbell","lastname":"Kendall","productNames":["Pet Insurance","Pet Insurance","Home Insurance","Bike Insurance"]},{"id":"c02","firstname":"Leilah","lastname":"Mandi","productNames":["Bike Insurance"]}]
    
    Login or Signup to reply.
  2. You can achieve this by iterating over the customers who made purchases, and then using map and find to get the product names associated with their purchases.
    The code first maps over the customersWhoPurchased array and, for each customer, finds their corresponding purchase record in data.purchases. Then, it maps over the purchases of the customer and, for each purchase, finds the corresponding product in data.products. Finally, it returns a new object with the same properties as the original customer object, but with an additional productNames property containing an array of product names.
    Here’s the code to do that:

    const customersWithProductNames = customersWhoPurchased.map((customer) => {
      // Get the corresponding purchase record for the customer
      const customerPurchases = data.purchases.find(
        (purchase) => purchase.customerId === customer.id
      );
    
      // Map the productIds in the purchases to their corresponding product names
      const productNames = customerPurchases.purchases.map((purchase) => {
        const product = data.products.find(
          (product) => product.id === purchase.productId
        );
        return product.name;
      });
    
      // Add the productNames array to the customer object and return it
      return {
        ...customer,
        productNames: productNames,
      };
    });
    
    console.log(customersWithProductNames);
    Expected Output:
    [
      {
        id: 'c01',
        firstname: 'Rachel',
        lastname: 'Jane',
        productNames: ['Car Insurance', 'Car Insurance', 'Bike Insurance', 'Bike Insurance']
      },
      {
        id: 'c02',
        firstname: 'Leilah',
        lastname: 'Mandi',
        productNames: ['Bike Insurance']
      },
      {
        id: 'c03',
        firstname: 'Campbell',
        lastname: 'Kendall',
        productNames: ['Pet Insurance', 'Pet Insurance', 'Home Insurance', 'Bike Insurance']
      }
    ]
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search