DEV Community

Cover image for JavaScript array methods: Solving the Scenario based Questions
Santosh Premi Adhikari
Santosh Premi Adhikari

Posted on

JavaScript array methods: Solving the Scenario based Questions

Let's go through each question and provide solutions using JavaScript array methods.

//Dataset 1: E-Commerce Product Sales

const products = [
  {
    id: 1,
    name: "Wireless Headphones",
    category: "Electronics",
    brand: "TechGadget",
    price: 149.99,
    rating: 4.7,
    soldUnits: 1200,
    reviews: [
      { userId: 101, comment: "Great sound quality!", rating: 5 },
      { userId: 102, comment: "Battery life is short", rating: 3 }
    ],
    relatedProducts: [2, 3]
  },
  {
    id: 2,
    name: "Smartwatch",
    category: "Electronics",
    brand: "FitWear",
    price: 199.99,
    rating: 4.2,
    soldUnits: 850,
    reviews: [
      { userId: 103, comment: "Love the fitness tracking", rating: 4 }
    ],
    relatedProducts: [1, 4]
  },
  // ... more products
];
//Dataset 2: User Activity Logs
const userActivity = [
  {
    userId: 101,
    username: "johndoe",
    actions: [
      { timestamp: "2023-10-05T09:15:00", action: "login", ip: "192.168.1.1" },
      { timestamp: "2023-10-05T09:20:30", action: "add_to_cart", product: "Wireless Headphones" },
      { timestamp: "2023-10-05T09:25:45", action: "checkout", amount: 149.99 }
    ],
    lastLogin: "2023-10-05T09:15:00",
    isActive: true
  },
  {
    userId: 102,
    username: "janedoe",
    actions: [
      { timestamp: "2023-10-05T10:30:00", action: "login", ip: "192.168.1.2" },
      { timestamp: "2023-10-05T10:35:00", action: "view_product", product: "Smartwatch" }
    ],
    lastLogin: "2023-10-05T10:30:00",
    isActive: false
  },
  // ... more users
];
Enter fullscreen mode Exit fullscreen mode

E-Commerce Product Sales Dataset

Question 1: Total Sales by Category

Calculate the total revenue generated per product category.

const totalSalesByCategory = products.reduce((acc, product) => {
  const category = product.category;
  const revenue = product.price * product.soldUnits;

  if (acc[category]) {
    acc[category] += revenue;
  } else {
    acc[category] = revenue;
  }

  return acc;
}, {});

console.log(totalSalesByCategory);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We use the reduce() method on the products array.
  2. The accumulator (acc) starts as an empty object.
  3. For each product, we calculate the revenue by multiplying price and soldUnits.
  4. We check if the product's category already exists in the accumulator.
  5. If it does, we add the revenue to the existing value.
  6. If it doesn't, we create a new property with the category name and set its value to the revenue.
  7. The result is an object where each key is a category and each value is the total revenue for that category.

Expected Output:

{
  Electronics: 149.99*1200 + 199.99*850 + 89.99*950 + ... (sum of all Electronics products),
  Accessories: 49.99*900 + 19.99*2500 + ... (sum of all Accessories products)
}
Enter fullscreen mode Exit fullscreen mode

Question 2: High-Selling Low-Rated Products

Find products with soldUnits > 1000 but rating < 4.0.

const highSellingLowRated = products.filter(product => 
  product.soldUnits > 1000 && product.rating < 4.0
);

console.log(highSellingLowRated);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We use the filter() method on the products array.
  2. The callback function checks if a product has soldUnits > 1000 and rating < 4.0.
  3. Only products that meet both conditions are included in the resulting array.

Expected Output:
An array of products that have sold more than 1000 units but have a rating below 4.0.

Question 3: Discounted Prices

Add a discountedPrice field to each product (15% off if rating >= 4.5, 10% otherwise).

const productsWithDiscount = products.map(product => {
  const discount = product.rating >= 4.5 ? 0.15 : 0.10;
  return {
    ...product,
    discountedPrice: product.price * (1 - discount)
  };
});

console.log(productsWithDiscount);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We use the map() method to create a new array with modified products.
  2. For each product, we determine the discount percentage based on its rating.
  3. We create a new object that includes all original properties plus the discountedPrice.
  4. The discountedPrice is calculated by applying the appropriate discount to the original price.

Expected Output:
An array of products where each product has an additional discountedPrice property.

Question 4: Top Reviewers

Extract unique user IDs of users who left reviews with a rating of 5.

const topReviewers = [...new Set(products.flatMap(product => 
  product.reviews
    .filter(review => review.rating === 5)
    .map(review => review.userId)
))];

console.log(topReviewers);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We use flatMap() to create a single array of all reviews across all products.
  2. We filter this array to keep only reviews with a rating of 5.
  3. We extract the userId from each of these reviews.
  4. We use Set to remove duplicate user IDs and convert it back to an array.

Expected Output:
An array of unique user IDs who left 5-star reviews.

Question 5: Related Product Chains

For each product, list its related products and their categories.

const productRelatedCategories = products.map(product => {
  return {
    productId: product.id,
    relatedProducts: product.relatedProducts.map(relatedId => {
      const relatedProduct = products.find(p => p.id === relatedId);
      return {
        id: relatedId,
        name: relatedProduct.name,
        category: relatedProduct.category
      };
    })
  };
});

console.log(productRelatedCategories);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We use map() to create a new array with transformed product information.
  2. For each product, we find its related products using their IDs.
  3. For each related product, we extract its ID, name, and category.
  4. The result is an array where each element contains the original product ID and information about its related products.

Expected Output:
An array where each element contains a product ID and an array of its related products with their details.

User Activity Logs Dataset

Question 6: Active Users with Recent Activity

Filter users who are isActive and logged in within the last 24 hours.

// Assuming today is 2023-10-06
const oneDayAgo = new Date("2023-10-05T00:00:00").toISOString();

const activeRecentUsers = userActivity.filter(user => 
  user.isActive && new Date(user.lastLogin) >= new Date(oneDayAgo)
);

console.log(activeRecentUsers);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We calculate the timestamp for 24 hours ago.
  2. We use filter() to find users who are active (isActive: true).
  3. We check if the user's lastLogin is within the last 24 hours.
  4. The result is an array of users who meet both conditions.

Expected Output:
An array of users who are active and logged in within the last 24 hours.

Question 7: Checkout Frequency

Count how many users completed a checkout action.

const checkoutCount = userActivity.reduce((count, user) => {
  const hasCheckout = user.actions.some(action => action.action === "checkout");
  return count + (hasCheckout ? 1 : 0);
}, 0);

console.log(checkoutCount);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We use reduce() to count the number of users who completed a checkout.
  2. For each user, we check if any of their actions is a checkout.
  3. We increment the count for each user who has at least one checkout action.
  4. The result is the total number of users who completed a checkout.

Expected Output:
A number representing how many users completed a checkout.

Question 8: Session Duration

Calculate the average time (in minutes) users spent between login and their last action.

const averageSessionDuration = userActivity
  .filter(user => user.actions.length > 0)
  .map(user => {
    const loginTime = new Date(user.actions[0].timestamp);
    const lastActionTime = new Date(user.actions[user.actions.length - 1].timestamp);
    return (lastActionTime - loginTime) / 60000; // Convert ms to minutes
  })
  .reduce((sum, duration) => sum + duration, 0) / userActivity.length;

console.log(averageSessionDuration);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We filter out users with no actions.
  2. For each remaining user, we calculate the time between their first (login) and last action.
  3. We convert the time difference from milliseconds to minutes.
  4. We use reduce() to sum all session durations.
  5. We divide by the number of users to get the average.
  6. The result is the average session duration in minutes.

Expected Output:
A number representing the average session duration in minutes.

Question 9: IP Address Analysis

Group users by their IP addresses and count how many actions each IP has.

const ipActionCount = userActivity.flatMap(user => 
  user.actions.map(action => ({
    ip: action.ip,
    userId: user.userId
  }))
).reduce((acc, action) => {
  if (acc[action.ip]) {
    acc[action.ip].count++;
    acc[action.ip].users.add(action.userId);
  } else {
    acc[action.ip] = { count: 1, users: new Set([action.userId]) };
  }
  return acc;
}, {});

console.log(ipActionCount);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We use flatMap() to create an array of all actions with their corresponding IP addresses.
  2. We use reduce() to group actions by IP address.
  3. For each IP address, we count the number of actions and track unique users.
  4. The result is an object where each key is an IP address and the value contains the action count and unique users.

Expected Output:
An object where each key is an IP address and the value is an object containing the action count and unique users for that IP.

Question 10: Product Popularity

Find the product viewed or purchased most frequently.

const productPopularity = userActivity
  .flatMap(user => user.actions
    .filter(action => action.action === "view_product" || action.action === "checkout")
    .map(action => action.product)
  )
  .reduce((acc, product) => {
    acc[product] = (acc[product] || 0) + 1;
    return acc;
  }, {});

const mostPopularProduct = Object.entries(productPopularity)
  .reduce((max, entry) => entry[1] > max[1] ? entry : max, ["", 0]);

console.log(mostPopularProduct);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We use flatMap() to create an array of all view_product and checkout actions.
  2. We extract the product names from these actions.
  3. We use reduce() to count how many times each product appears.
  4. We find the product with the highest count using another reduce().
  5. The result is the most popular product and its count.

Expected Output:
An array where the first element is the most popular product name and the second element is its count.

Combined Challenges

Question 11: User Purchase History

For each user, create an array of products they purchased (filter checkout actions).

const userPurchaseHistory = userActivity.map(user => {
  return {
    userId: user.userId,
    purchases: user.actions
      .filter(action => action.action === "checkout")
      .map(action => {
        const product = products.find(p => p.name === action.product);
        return {
          name: action.product,
          price: product.price,
          quantity: 1 // Assuming each checkout is for one unit
        };
      })
  };
});

console.log(userPurchaseHistory);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We use map() to create a new array with purchase history for each user.
  2. For each user, we filter their actions to find checkout actions.
  3. For each checkout action, we find the corresponding product in the products array.
  4. We create an object with purchase details (name, price, quantity).
  5. The result is an array where each element contains a user ID and their purchase history.

Expected Output:
An array where each element contains a user ID and an array of their purchases.

Question 12: Cross-Sell Opportunities

For users who bought "Wireless Headphones", suggest related products from the sales dataset.

const wirelessHeadphones = products.find(p => p.name === "Wireless Headphones");
const relatedProductIds = wirelessHeadphones.relatedProducts;

const crossSellSuggestions = products
  .filter(p => relatedProductIds.includes(p.id) && p.name !== "Wireless Headphones")
  .map(p => ({
    id: p.id,
    name: p.name,
    category: p.category
  }));

console.log(crossSellSuggestions);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We find the "Wireless Headphones" product in the products array.
  2. We extract the IDs of its related products.
  3. We filter the products array to find products with matching IDs (excluding the headphones themselves).
  4. We map these products to a simplified format.
  5. The result is an array of suggested cross-sell products.

Expected Output:
An array of products related to "Wireless Headphones" that could be suggested for cross-selling.

Question 13: Fraud Detection

Identify users who logged in from multiple unique IPs in a single day.

const usersWithMultipleIPs = userActivity.filter(user => {
  const loginActions = user.actions.filter(action => action.action === "login");
  const ips = new Set(loginActions.map(action => action.ip));
  return ips.size > 1;
});

console.log(usersWithMultipleIPs);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We filter users to find those with multiple login IPs.
  2. For each user, we filter their actions to find login actions.
  3. We extract the IPs from these login actions and store them in a Set (which automatically removes duplicates).
  4. We check if the size of the Set is greater than 1.
  5. The result is an array of users who logged in from multiple unique IPs.

Expected Output:
An array of users who logged in from multiple unique IPs.

Question 14: Revenue per User

Calculate the total spend per user (sum amount from checkout actions).

const revenuePerUser = userActivity.map(user => {
  const totalSpent = user.actions
    .filter(action => action.action === "checkout")
    .reduce((sum, action) => sum + action.amount, 0);
  return {
    userId: user.userId,
    username: user.username,
    totalSpent: totalSpent
  };
});

console.log(revenuePerUser);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We use map() to create an array with spending information for each user.
  2. For each user, we filter their actions to find checkout actions.
  3. We use reduce() to sum the amounts from these checkout actions.
  4. We create an object with the user's ID, username, and total spent.
  5. The result is an array where each element contains a user's spending information.

Expected Output:
An array where each element contains a user's ID, username, and total amount spent.

Question 15: Best-Selling Brands

Rank brands by total revenue generated from sold units.

const brandRevenue = products.reduce((acc, product) => {
  const revenue = product.price * product.soldUnits;
  if (acc[product.brand]) {
    acc[product.brand] += revenue;
  } else {
    acc[product.brand] = revenue;
  }
  return acc;
}, {});

const rankedBrands = Object.entries(brandRevenue)
  .sort((a, b) => b[1] - a[1]);

console.log(rankedBrands);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We use reduce() to calculate total revenue per brand.
  2. For each product, we calculate revenue and accumulate it by brand.
  3. We convert the resulting object to an array of entries.
  4. We sort this array in descending order based on revenue.
  5. The result is an array of brands ranked by their total revenue.

Expected Output:
An array where each element is a brand and its total revenue, sorted from highest to lowest.

Advanced Aggregations

Question 16: Monthly Sales Trend

Group product sales by month (extract from lastLogin or action timestamps).

const monthlySales = userActivity
  .flatMap(user => user.actions
    .filter(action => action.action === "checkout")
    .map(action => ({
      month: new Date(action.timestamp).getMonth() + 1, // Months are 0-based
      amount: action.amount
    }))
  )
  .reduce((acc, sale) => {
    if (acc[sale.month]) {
      acc[sale.month].total += sale.amount;
      acc[sale.month].transactions++;
    } else {
      acc[sale.month] = { total: sale.amount, transactions: 1 };
    }
    return acc;
  }, {});

console.log(monthlySales);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We use flatMap() to create an array of all checkout actions with their month and amount.
  2. We extract the month from each action's timestamp.
  3. We use reduce() to accumulate total sales and transaction counts per month.
  4. The result is an object where each key is a month number and the value contains total sales and transaction count.

Expected Output:
An object where each key is a month number (1-12) and the value is an object containing total sales and transaction count for that month.

Question 17: User Engagement Score

Assign a score to each user based on actions (e.g., login=1, add_to_cart=3, checkout=5).

const engagementScores = userActivity.map(user => {
  const score = user.actions.reduce((total, action) => {
    switch(action.action) {
      case "login": return total + 1;
      case "view_product": return total + 2;
      case "add_to_cart": return total + 3;
      case "checkout": return total + 5;
      case "remove_from_cart": return total - 2;
      default: return total;
    }
  }, 0);
  return {
    userId: user.userId,
    username: user.username,
    score: score,
    engagementLevel: score > 10 ? "high" : score > 5 ? "medium" : "low"
  };
});

console.log(engagementScores);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We use map() to create an array with engagement scores for each user.
  2. For each user, we calculate their score based on their actions.
  3. Different actions contribute different amounts to the score.
  4. We categorize the engagement level based on the total score.
  5. The result is an array where each element contains a user's engagement score and level.

Expected Output:
An array where each element contains a user's ID, username, engagement score, and engagement level.

Question 18: Product Review Sentiment

Average the ratings for each product and flag those with an average below 3.5.

const productRatings = products.map(product => {
  const totalRatings = product.reviews.reduce((sum, review) => sum + review.rating, 0);
  const averageRating = totalRatings / product.reviews.length;
  return {
    id: product.id,
    name: product.name,
    averageRating: averageRating,
    needsImprovement: averageRating < 3.5
  };
});

console.log(productRatings);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We use map() to create an array with rating information for each product.
  2. For each product, we calculate the total of all review ratings.
  3. We divide by the number of reviews to get the average rating.
  4. We flag products with an average rating below 3.5.
  5. The result is an array where each element contains a product's rating information.

Expected Output:
An array where each element contains a product's ID, name, average rating, and a flag indicating if improvement is needed.

Question 19: Cart Abandonment

Find users who added items to their cart but never checked out.

const cartAbandoners = userActivity.filter(user => {
  const addedToCart = user.actions.some(action => action.action === "add_to_cart");
  const checkedOut = user.actions.some(action => action.action === "checkout");
  return addedToCart && !checkedOut;
});

console.log(cartAbandoners);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. We filter users to find those who added items to their cart but never checked out.
  2. For each user, we check if they have any "add_to_cart" actions.
  3. We check if they have any "checkout" actions.
  4. We include users who have added to cart but haven't checked out.
  5. The result is an array of users who abandoned their cart.

Expected Output:
An array of users who added items to their cart but never completed a checkout.

Question 20: Brand Loyalty

For each brand, calculate the percentage of users who purchased multiple products from it.

// First, create a map of users to the brands they purchased
const userBrandPurchases = userActivity.map(user => {
  const purchasedBrands = new Set();
  user.actions
    .filter(action => action.action === "checkout")
    .forEach(action => {
      const product = products.find(p => p.name === action.product);
      if (product) purchasedBrands.add(product.brand);
    });
  return {
    userId: user.userId,
    purchasedBrands: purchasedBrands
  };
});

// Then, calculate brand loyalty
const brandLoyalty = products
  .reduce((acc, product) => {
    acc[product.brand] = { 
      loyalUsers: 0, 
      totalUsers: 0 
    };
    return acc;
  }, {})

userBrandPurchases.forEach(user => {
  if (user.purchasedBrands.size === 1) {
    const brand = user.purchasedBrands.values().next().value;
    brandLoyalty[brand].loyalUsers++;
  }
  user.purchasedBrands.forEach(brand => {
    brandLoyalty[brand].totalUsers++;
  });
});

// Calculate percentages
const brandLoyaltyPercentages = Object.entries(brandLoyalty).map(([brand, data]) => {
  return {
    brand: brand,
    loyaltyPercentage: (data.loyalUsers / data.totalUsers * 100).toFixed(2)
  };
});

console.log(brandLoyaltyPercentages);
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Explanation:

  1. First, we create a map of users to the brands they purchased.
  2. For each user, we find all brands they purchased through their checkout actions.
  3. We then initialize a loyalty tracker for each brand.
  4. For each user, if they only purchased from one brand, we count them as loyal to that brand.
  5. We count the total number of users who purchased from each brand.
  6. Finally, we calculate the loyalty percentage for each brand.
  7. The result is an array where each element contains a brand and its loyalty percentage.

Expected Output:
An array where each element contains a brand name and the percentage of users who purchased only that brand.

These solutions demonstrate how to use JavaScript array methods to manipulate and analyze complex datasets, similar to what you might encounter in real-world software development scenarios.

Top comments (0)

👋 Kindness is contagious

If you found this post useful, please drop a ❤️ or leave a kind comment!

Okay