Data
var ranges = [
{ start: 2, end: 5 },
{ start: 8, end: 12 },
{ start: 15, end: 20 },
{ start: 9, end: 11 },
{ start: 2, end: 6 }
];
Each object represents a range. I need to remove the ranges that are contained into another. That is, between two redundant objects I need to keep the longer range.
I wrote this code, but I wonder if there is a better way to achieve this using lodash.
var Range = {
contains: function(r1, r2) {
return r2.start >= r1.start && r2.end <= r1.end;
}
};
var result = _.chain(ranges)
.filter(function(r2) {
return !_.some(ranges, function(r1) {
return r1 != r2 && Range.contains(r1, r2);
});
})
.value();
console.log(result);
Output
[
{ start: 8, end: 12 },
{ start: 15, end: 20 },
{ start: 2, end: 6 }
]
We can remove duplicate elements from an array using the _. uniq() method of Lodash. This method keeps the first instance of an element and removes the remaining one. Therefore, the order of an element in the resultant array depends on its occurrence in the array.
uniq() function compares values using SameValueZero comparison. SameValueZero works well for primitive values, but not for objects. The uniqBy() function is similar to the uniq() function, with the key difference that it allows you to pass in a function that returns the value you want to compare by.
The _. sortBy() method creates an array of elements which is sorted in ascending order by the results of running each element in a collection through each iteratee. And also this method performs a stable sort which means it preserves the original sort order of equal elements.
I finally found a simple way to achieve this using uniqWith.
var result = _.chain(ranges)
.orderBy(['end'], ['desc'])
.uniqWith(function(r1, r2) {
return Range.contains(r2, r1);
})
.value();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With