This question is specific to lodash.
Given two arrays of objects, what is the best way to filter one array with the objects of the other array? I have attempted to put forth a scenario below, and the way I have gone about doing this is using two .forEach
loops, but I would like to know if using lodash there is a better way to go about this type of filtering.
users
.
var users = [
{ 'user': 'barney', 'age': 36, 'active': true },
{ 'user': 'joe', 'age': 40, 'active': false },
{ 'user': 'fred', 'age': 50, 'active': false },
{ 'user': 'fred', 'age': 60, 'active': false },
{ 'user': 'fred', 'age': 70, 'active': false },
{ 'user': 'fred', 'age': 22, 'active': false },
{ 'user': 'fred', 'age': 25, 'active': false },
{ 'user': 'barney', 'age': 40, 'active': false },
{ 'user': 'pebbles', 'age': 1, 'active': true }
];
The array of objects that will filter the users
array is called others
.
var others = [
{ 'user': 'fred', 'age': 60 },
{ 'user': 'fred', 'age': 70},
{ 'user': 'fred', 'age': 22}
];
The desired result based on others
filtering users
is:
[
{ 'user': 'fred', 'age': 60, 'active': false },
{ 'user': 'fred', 'age': 70, 'active': false },
{ 'user': 'fred', 'age': 22, 'active': false }
];
Here is one way to obtain the desired result.
var result = [];
_.forEach(users, function (n, key) {
_.forEach(others, function (n2, key2) {
if (n.user === n2.user && n.age === n2.age) {
result.push(n);
}
});
});
console.log(result);
Here is the example on jsbin.
http://jsbin.com/hapariviya/1/edit?html,js,console,output
One can use filter() function in JavaScript to filter the object array based on attributes. The filter() function will return a new array containing all the array elements that pass the given condition. If no elements pass the condition it returns an empty array.
The filter() method creates a new array filled with elements that pass a test provided by a function. The filter() method does not execute the function for empty elements. The filter() method does not change the original array.
Yes, the . filter() method returns a new array, without the filtered elements in the same order as initially. The order of the elements is one of the main feature of a array.
You can index the others, and then get the desired results without having to nest loops. It should be a relatively efficient solution, regardless of the amount of data:
// index others by "user + age"
var lookup = _.keyBy(others, function(o) { return o.user + o.age.toString() });
// find all users where "user + age" exists in index, one loop, quick lookup. no nested loops
var result = _.filter(users, function(u) {
return lookup[u.user + u.age.toString()] !== undefined;
});
This gives the same result:
[
{ 'user': 'fred', 'age': 60, 'active': false },
{ 'user': 'fred', 'age': 70, 'active': false },
{ 'user': 'fred', 'age': 22, 'active': false }
];
Interestingly, your original solution was the most performant of all of these answers.
http://jsperf.com/testingdiwq
The performance concerns are pretty negligible here. In most cases, the DOM interaction is the main performance bottleneck of the front-end. If you were to run this against huge datasets and noticed the locking, you'd definitely want to optimize it further by using for loops instead of iterating with lodash functions.... but you won't typically come across that kind of data in JavaScript... SQL and others would handle it better.
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