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.

Updated on: 2026-03-15T23:19:00+05:30

241 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements