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
Group values in array by two properties JavaScript
We have an array of objects like this:
const arr = [
{ value: 12, gap: 1 },
{ value: 13, gap: 1 },
{ value: 14, gap: 1 },
{ value: 15, gap: 1 },
{ value: 19, gap: 2 },
{ value: 21, gap: 1 },
{ value: 22, gap: 1 },
{ value: 23, gap: 1 },
{ value: 27, gap: 1 },
{ value: 31, gap: 4 },
{ value: 35, gap: 4 },
{ value: 39, gap: 4 },
{ value: 43, gap: 1 },
{ value: 50, gap: 1 },
{ value: 51, gap: 1 },
{ value: 52, gap: 1 },
{ value: 55, gap: 1 },
{ value: 57, gap: 1 },
];
We need to write a function that groups consecutive objects where each object's value equals the sum of the previous object's value and gap. Objects that follow this pattern should be grouped together in subarrays.
For example, the object with value 12 has gap 1, and the next object has value 13 (12 + 1 = 13), so they must be grouped together along with objects having values 14 and 15.
Understanding the Logic
The grouping rule is: if current.value === previous.value + previous.gap, then the current object belongs to the same group as the previous one. Otherwise, start a new group.
Solution Using Array.reduce()
We'll use Array.prototype.reduce() to construct the grouped array by tracking the current group and checking the continuity condition:
const arr = [
{ value: 12, gap: 1 },
{ value: 13, gap: 1 },
{ value: 14, gap: 1 },
{ value: 15, gap: 1 },
{ value: 19, gap: 2 },
{ value: 21, gap: 1 },
{ value: 22, gap: 1 },
{ value: 23, gap: 1 },
{ value: 27, gap: 1 },
{ value: 31, gap: 4 },
{ value: 35, gap: 4 },
{ value: 39, gap: 4 },
{ value: 43, gap: 1 },
{ value: 50, gap: 1 },
{ value: 51, gap: 1 },
{ value: 52, gap: 1 },
{ value: 55, gap: 1 },
{ value: 57, gap: 1 },
];
const groupArray = arr => {
return arr.reduce((acc, val, ind, array) => {
// the accumulated data and currentIndex of accumulated data
const { data, currentIndex } = acc;
// the current object properties
const { value, gap } = val;
// the previous object properties
const v = arr[ind-1]?.value;
const g = arr[ind-1]?.gap;
if(ind === 0 || value !== v + g){
// recording the index of last object and pushing new subarray
const index = data.push([val]) - 1;
return { data, currentIndex: index };
};
data[currentIndex].push(val);
return { data, currentIndex };
}, {
data: [],
currentIndex: 0
}).data;
}
console.log(JSON.stringify(groupArray(arr), null, 2));
[
[
{ "value": 12, "gap": 1 },
{ "value": 13, "gap": 1 },
{ "value": 14, "gap": 1 },
{ "value": 15, "gap": 1 }
],
[
{ "value": 19, "gap": 2 },
{ "value": 21, "gap": 1 },
{ "value": 22, "gap": 1 },
{ "value": 23, "gap": 1 }
],
[
{ "value": 27, "gap": 1 }
],
[
{ "value": 31, "gap": 4 },
{ "value": 35, "gap": 4 },
{ "value": 39, "gap": 4 },
{ "value": 43, "gap": 1 }
],
[
{ "value": 50, "gap": 1 },
{ "value": 51, "gap": 1 },
{ "value": 52, "gap": 1 }
],
[
{ "value": 55, "gap": 1 }
],
[
{ "value": 57, "gap": 1 }
]
]
How It Works
The function uses an accumulator object with two properties:
-
data: Array of grouped subarrays -
currentIndex: Index of the current group being built
For each object, it checks if current.value === previous.value + previous.gap. If true, it adds the object to the current group. If false, it starts a new group.
Alternative Approach Using forEach
const groupArraySimple = arr => {
const result = [];
let currentGroup = [];
arr.forEach((obj, index) => {
if (index === 0) {
currentGroup = [obj];
} else {
const prevObj = arr[index - 1];
if (obj.value === prevObj.value + prevObj.gap) {
currentGroup.push(obj);
} else {
result.push(currentGroup);
currentGroup = [obj];
}
}
});
if (currentGroup.length > 0) {
result.push(currentGroup);
}
return result;
};
console.log(JSON.stringify(groupArraySimple(arr), null, 2));
Conclusion
Both approaches successfully group consecutive objects based on the value-gap relationship. The reduce() method provides a functional programming approach, while the forEach() method offers a more straightforward imperative solution. Choose the approach that best fits your coding style and team preferences.
