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
];
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);
Step-by-Step Explanation:
- We use the
reduce()
method on theproducts
array. - The accumulator (
acc
) starts as an empty object. - For each product, we calculate the revenue by multiplying
price
andsoldUnits
. - We check if the product's
category
already exists in the accumulator. - If it does, we add the revenue to the existing value.
- If it doesn't, we create a new property with the category name and set its value to the revenue.
- 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)
}
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);
Step-by-Step Explanation:
- We use the
filter()
method on theproducts
array. - The callback function checks if a product has
soldUnits > 1000
andrating < 4.0
. - 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);
Step-by-Step Explanation:
- We use the
map()
method to create a new array with modified products. - For each product, we determine the discount percentage based on its rating.
- We create a new object that includes all original properties plus the
discountedPrice
. - 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);
Step-by-Step Explanation:
- We use
flatMap()
to create a single array of all reviews across all products. - We filter this array to keep only reviews with a rating of 5.
- We extract the
userId
from each of these reviews. - 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);
Step-by-Step Explanation:
- We use
map()
to create a new array with transformed product information. - For each product, we find its related products using their IDs.
- For each related product, we extract its ID, name, and category.
- 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);
Step-by-Step Explanation:
- We calculate the timestamp for 24 hours ago.
- We use
filter()
to find users who are active (isActive: true
). - We check if the user's
lastLogin
is within the last 24 hours. - 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);
Step-by-Step Explanation:
- We use
reduce()
to count the number of users who completed a checkout. - For each user, we check if any of their actions is a checkout.
- We increment the count for each user who has at least one checkout action.
- 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);
Step-by-Step Explanation:
- We filter out users with no actions.
- For each remaining user, we calculate the time between their first (login) and last action.
- We convert the time difference from milliseconds to minutes.
- We use
reduce()
to sum all session durations. - We divide by the number of users to get the average.
- 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);
Step-by-Step Explanation:
- We use
flatMap()
to create an array of all actions with their corresponding IP addresses. - We use
reduce()
to group actions by IP address. - For each IP address, we count the number of actions and track unique users.
- 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);
Step-by-Step Explanation:
- We use
flatMap()
to create an array of all view_product and checkout actions. - We extract the product names from these actions.
- We use
reduce()
to count how many times each product appears. - We find the product with the highest count using another
reduce()
. - 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);
Step-by-Step Explanation:
- We use
map()
to create a new array with purchase history for each user. - For each user, we filter their actions to find checkout actions.
- For each checkout action, we find the corresponding product in the products array.
- We create an object with purchase details (name, price, quantity).
- 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);
Step-by-Step Explanation:
- We find the "Wireless Headphones" product in the products array.
- We extract the IDs of its related products.
- We filter the products array to find products with matching IDs (excluding the headphones themselves).
- We map these products to a simplified format.
- 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);
Step-by-Step Explanation:
- We filter users to find those with multiple login IPs.
- For each user, we filter their actions to find login actions.
- We extract the IPs from these login actions and store them in a Set (which automatically removes duplicates).
- We check if the size of the Set is greater than 1.
- 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);
Step-by-Step Explanation:
- We use
map()
to create an array with spending information for each user. - For each user, we filter their actions to find checkout actions.
- We use
reduce()
to sum the amounts from these checkout actions. - We create an object with the user's ID, username, and total spent.
- 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);
Step-by-Step Explanation:
- We use
reduce()
to calculate total revenue per brand. - For each product, we calculate revenue and accumulate it by brand.
- We convert the resulting object to an array of entries.
- We sort this array in descending order based on revenue.
- 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);
Step-by-Step Explanation:
- We use
flatMap()
to create an array of all checkout actions with their month and amount. - We extract the month from each action's timestamp.
- We use
reduce()
to accumulate total sales and transaction counts per month. - 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);
Step-by-Step Explanation:
- We use
map()
to create an array with engagement scores for each user. - For each user, we calculate their score based on their actions.
- Different actions contribute different amounts to the score.
- We categorize the engagement level based on the total score.
- 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);
Step-by-Step Explanation:
- We use
map()
to create an array with rating information for each product. - For each product, we calculate the total of all review ratings.
- We divide by the number of reviews to get the average rating.
- We flag products with an average rating below 3.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);
Step-by-Step Explanation:
- We filter users to find those who added items to their cart but never checked out.
- For each user, we check if they have any "add_to_cart" actions.
- We check if they have any "checkout" actions.
- We include users who have added to cart but haven't checked out.
- 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);
Step-by-Step Explanation:
- First, we create a map of users to the brands they purchased.
- For each user, we find all brands they purchased through their checkout actions.
- We then initialize a loyalty tracker for each brand.
- For each user, if they only purchased from one brand, we count them as loyal to that brand.
- We count the total number of users who purchased from each brand.
- Finally, we calculate the loyalty percentage for each brand.
- 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)