Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Selected Reading
Complicated array grouping JavaScript
Suppose we have an array of objects like this ?
const arr = [
{userId: "3t5bsFB4PJmA3oTnm", from: 1, to: 6},
{userId: "3t5bsFB4PJmA3oTnm", from: 7, to: 15},
{userId: "3t5bsFB4PJmA3oTnm", from: 172, to: 181},
{userId: "3t5bsFB4PJmA3oTnm", from: 182, to: 190}
];
We need to write a JavaScript function that groups consecutive objects based on their "from" and "to" properties. Objects are considered consecutive when the "to" value of one object plus 1 equals the "from" value of the next object with the same userId.
Expected Output
[
{userId: "3t5bsFB4PJmA3oTnm", from: 1, to: 15},
{userId: "3t5bsFB4PJmA3oTnm", from: 172, to: 190}
]
Implementation Using Array.reduce()
const arr = [
{userId: "3t5bsFB4PJmA3oTnm", from: 1, to: 6},
{userId: "3t5bsFB4PJmA3oTnm", from: 7, to: 15},
{userId: "3t5bsFB4PJmA3oTnm", from: 172, to: 181},
{userId: "3t5bsFB4PJmA3oTnm", from: 182, to: 190}
];
const groupByDuration = (arr = []) => {
const result = arr.reduce((acc, val) => {
let last = acc[acc.length - 1] || {};
if (last.userId === val.userId && last.to + 1 === val.from) {
last.to = val.to;
} else {
acc.push({ userId: val.userId, from: val.from, to: val.to });
}
return acc;
}, []);
return result;
}
console.log(groupByDuration(arr));
[
{ userId: '3t5bsFB4PJmA3oTnm', from: 1, to: 15 },
{ userId: '3t5bsFB4PJmA3oTnm', from: 172, to: 190 }
]
How It Works
The algorithm works by:
- Using
reduce()to iterate through the array and build the result - Checking if the current object can be merged with the last object in the accumulator
- Two conditions must be met: same userId and consecutive ranges (last.to + 1 === val.from)
- If mergeable, extending the "to" property of the last object
- If not mergeable, adding a new object to the result
Example with Multiple Users
const complexArr = [
{userId: "user1", from: 1, to: 5},
{userId: "user1", from: 6, to: 10},
{userId: "user2", from: 20, to: 25},
{userId: "user2", from: 30, to: 35},
{userId: "user1", from: 50, to: 55}
];
console.log(groupByDuration(complexArr));
[
{ userId: 'user1', from: 1, to: 10 },
{ userId: 'user2', from: 20, to: 25 },
{ userId: 'user2', from: 30, to: 35 },
{ userId: 'user1', from: 50, to: 55 }
]
Conclusion
This approach efficiently groups consecutive ranges using Array.reduce(). The key insight is checking if ranges are adjacent (to + 1 === from) and belong to the same user before merging them.
Advertisements
