I have array of users who have a property array 'rights' and I want to filter out the users who have specific rights. I would like to filter by an array so if I wanted all the users with full rights ['full'] or users with both full and edit ['full','edit']. I am fairly new to using lodash and I think I can chain some together but I am not sure if this is there are more efficient ways of doing it.
Here is my plunker: http://plnkr.co/edit/5PCvaDJaXF4uxRowVBlK?p=preview
Result ['full'] :
[{
"name": "Company1 Admin",
"rights": [
"full"
]
},
{
"name": "FullRights Company1",
"rights": [
"full","review"
]
}]
Result ['full','edit']:
[{
"name": "Company1 Admin",
"rights": [
"full"
]
},
{
"name": "FullRights Company1",
"rights": [
"full","review"
]
},
{
"name": "EditRights Company1",
"rights": [
"edit"
]
}]
Code:
var users = [
{
"name": "Company1 Admin",
"rights": [
"full"
]
},
{
"name": "FullRights Company1",
"rights": [
"full","review"
]
},
{
"name": "ApproveRights Company1",
"rights": [
"approve","review"
]
},
{
"name": "EditRights Company1",
"rights": [
"edit"
]
},
{
"name": "ReviewRights Company1",
"rights": [
"review"
]
},
{
"name": "NoRights Company1",
"rights": [
"none"
]
}
];
var tUsers = [];
var filterRights = ['full','edit'];
_.forEach(users, function(user) {
if (_.intersection(user.rights, filterRights).length > 0) {
tUsers.push(user);
}
}) ;
//console.log('users', JSON.stringify(users, null, 2));
console.log('tUsers', JSON.stringify(tUsers, null, 2));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
_.filter(collection, predicate, thisArg);
Arguments
collection (Array|Object|string): The collection to iterate over.
[predicate=_.identity] (Function|Object|string): The function invoked per iteration.
[thisArg] (*): The this binding of predicate.
Chaining is great when you want to connect different processing steps.
If your problem statement was to
Then chaining would make a lot of sense.
This problem seems to be mostly custom logic on filtering.
var users = [/* Your user data here */];
function filterByRights (users, rights) {
return _.filter(users, function (user) {
return _.any(user.rights, function (right) {
return _.contains(rights, right);
});
});
}
filterByRights(users, ['full', 'edit']); // [/*Users with full or edit rights*/]
I think my example is good becuase it doesn't depend on conditional logic. It uses lodash defined methods like any
and contains
I want to expand on what performance concerns you have. Here are a couple of points.
Your question code is maintaining its own mechanism for filtering out users. While it is a perfectly good solution you should opt into letting the guys who maintain lodash handle this logic. They have probably spent a lot of time optimizing how to create another array from an original one.
_.any
is more efficient than _.intersection
. _.intersection
needs to process every element to know what the intersection is. _.any
stops when it hits the first element which passes the predicate otherwise it checks each of them. This point is minor since there are a small number of "rights"
The example I've given is probably more "lodash standard". You typically can do data transformations completely with lodash defined methods and trivial predicates.
Here is an update to @t3dodson 's answer. You should now use the following snippet if using current (4.17.4) Lodash version:
function filterByRights (users, rights) {
return _.filter(users, function (user) {
return _.some(user.rights, function (right) {
return _.includes(rights, right);
});
});
}
From the Changelog:
Removed _.contains in favor of _.includes
Removed _.any in favor of _.some
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