Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter redundant objects from array with lodash

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 }
]
like image 400
jcbp Avatar asked Aug 19 '16 15:08

jcbp


People also ask

How do you remove duplicates in array of objects in Lodash?

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.

Does Lodash Uniq work on objects?

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.

How do you sort an array of objects in Lodash?

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.


1 Answers

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();
like image 197
jcbp Avatar answered Oct 25 '22 02:10

jcbp