I am trying to use underscoreJs to manipulate a JavaScript object and having problems doing so.
Here is my example
var data = {
"label": "SomeName",
"parent": [{
"id": "parentId",
"resources": [{
"name": "ID1NAME",
"calls": [
"user_get", "user2_post", "user3_delete"
]
}, {
"name": "ID2",
"calls": [
"employee1_get", "employee2_delete", "employee3_update"
]
}]
}]
};
var res = _(data).chain().
pluck('parent').
flatten().
findWhere(function(item){
item === "user_get"
}).
value();
console.log(res);
Using an element which is a part of data.parent.calls[]
(example : "user_get") I would like to extract its parent object, i.e. data.parent[0]
.
I tried above but always get undefined. I appreciate any help on this.
One of the problems you're having is your use of _.pluck
. If you execute _.pluck
over an object, it'll go over the keys of the object trying to retrieve the property you specified as the second argument (in this case, 'parent'). 'label' is a string and 'parent' is an array so thus the array that you get as a result is [undefined, undefined]
. The rest will then go wrong.
One solution could be as follows:
function findCallIndexInParent(call, parent) {
return _.chain(parent)
.pluck('resources')
.flatten()
.findIndex(function (obj) {
return _.contains(obj.calls, call);
})
.value();
}
function findCall(call, data) {
var parent = data.parent;
return parent[findCallIndexInParent(call, parent)];
}
console.log(findCall('user_get', data));
findCall
is just a convenient method that will pass the parent property of data to findCallIndexInParent
(that will retrieve the index where call is) and return the desired object with the parent array.
Lodash (a fork of underscore) provides a method to get the property of an object that would have come really handy in here (sadly, underscore doesn't have it).
The explanation of findCallIndexInParent
is as follows:
- Chain the parent list
- pluck the resources array
- As pluck maps, it returns a list of lists so a flatten is needed.
- Find the index of the element which calls contains call
- Return the value (the index) of the object that contains call within parent.
Here's the fiddle. Hope it helps.
This would seem to do the trick.
function findByCall(data, call) {
return _.find(data.parent, function(parent) { //From data.parent list, find an item that
return _.some(parent.resources, function(resource) {//has such parent.resource that it
return _.includes(resource.calls, call); //includes the searched resource.calls item
});
});
}
//Test
var data = {
"label": "SomeName",
"parent": [{
"id": "parentId",
"resources": [{
"name": "ID1NAME",
"calls": [
"user_get", "user2_post", "user3_delete"
]
}, {
"name": "ID2",
"calls": [
"employee1_get", "employee2_delete", "employee3_update"
]
}]
}]
};
console.log(findByCall(data, 'user_get'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
If I understand correctly, you want to get the index of the element in the parent
array which has any resource with the specified call.
data = {
"label": "SomeName",
"parent": [{
"id": "parentId",
"resources": [{
"name": "ID1NAME",
"calls": [
"user_get", "user2_post", "user3_delete"
]
}, {
"name": "ID2",
"calls": [
"employee1_get", "employee2_delete", "employee3_update"
]
}]
}]
}
// find the index of a parent
const index = _.findIndex(data.parent, parent =>
// that has any (some) resources
_.some(parent.resources, resource =>
// that contains 'user_get' call in its calls list
_.contains(resource.calls, 'user_get')
)
)
console.log(index) // 0
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
If you want to find the actual parent object, use find
instead of findIndex
If you want to find all parent objects matching this call, use filter
instead of findIndex