[Medium] Implement consolidate data
March 7, 2024
Question Prompt
Imagine you're working with a reading app that tracks users' reading sessions. The app logs data in the following format:
const sessions = [
{ user: 8, duration: 50, books: ["The Hobbit"] },
{ user: 7, duration: 150, books: ["Pride and Prejudice"] },
{ user: 1, duration: 10, books: ["The Lord of the Rings"] },
{ user: 7, duration: 100, books: ["The Great Gatsby", "Animal Farm"] },
{ user: 7, duration: 200, books: ["The Great Gatsby"] },
{ user: 2, duration: 200, books: ["1984"] },
{ user: 2, duration: 200, books: ["The Great Gatsby"] },
];
Each session object has the following fields:
user
: The user ID of the reader.duration
: The duration of the reading session in minutes.books
: An array of book titles read during the session, sorted alphabetically.
Implement a method named consolidateData
that merges data from sessions for each user, providing a unified overview of their reading activities. The method should have the interface consolidateData(sessions)
.
Merging Rules:
- Combine sessions for the same
user
into a single object. - Sum up the
duration
fields for the merged sessions. - Combine the
books
arrays, removing duplicates and sorting alphabetically. - Maintain the original order of the results.
- If multiple sessions belong to the same user, the merged session should take the place of the earliest occurrence of that user in the original set.
- Do not modify the input objects.
The expected output of the input above should be
[
{ user: 8, duration: 50, books: ["The Hobbit"] },
{
user: 7,
duration: 450,
books: ["Animal Farm", "Pride and Prejudice", "The Great Gatsby"],
},
{ user: 1, duration: 10, books: ["The Lord of the Rings"] },
{ user: 2, duration: 400, books: ["1984", "The Great Gatsby"] },
];
Solutions
Looking to practice more questions like these? We recommend GreatFrontEnd, the best platform for honing your frontend interview skills!
We start by creating an empty array, mergedData
, which will store the final merged session objects. Additionally, we initialize a Set
, seenUsers
, to keep track of the user IDs we've processed. This helps in maintaining the order and ensuring that we don't process a user more than once in terms of creating a new entry.
Then, iterate over each session object in the provided sessions
array. For each session, we extract the userId
to determine whether it's a session from a new user or an existing one.
If the user (userId
) has already been seen (i.e., it exists in the seenUsers
set), we find the index of this user's data in the mergedData
array. This is necessary because we need to update this specific user's consolidated data.
Once we have the index, we update the duration
by adding the current session's duration to the existing total.For the books
array, we merge the existing books list with the current session's books, ensuring there are no duplicates by converting it into a Set
. We then convert this set back into an array and sort it to maintain a consistent order.
If the user has not been seen before, we create a new object containing the user's ID, the duration of the current session, and the books list (which we assume is unique and sorted for each session). This object is then added to the mergedData
array, and the user ID is added to the seenUsers
set to mark that the user has been processed.
After iterating through all session objects, we return the mergedData
array, which now contains the consolidated session data for each user, with durations summed up and books lists deduplicated and sorted.
function consolidateData(sessions) {
const mergedData = [];
const seenUsers = new Set(); // Track seen users to maintain order
for (const session of sessions) {
const userId = session.user;
// Check if user already seen
if (seenUsers.has(userId)) {
const existingIndex = mergedData.findIndex(
(user) => user.user === userId
);
// Update existing user data
mergedData[existingIndex].duration += session.duration;
mergedData[existingIndex].books = Array.from(
new Set([...mergedData[existingIndex].books, ...session.books])
).sort(); // Deduplicate and sort books
} else {
// New user, add merged data
mergedData.push({
user: userId,
duration: session.duration,
books: session.books,
});
seenUsers.add(userId);
}
}
return mergedData;
}