Reputation: 619
I am using _.pick method in the following manner
suppose I have an array of strings which are nothing but property names I want to get from each object in array of objects
var wantedPropArray=["prop1","prop2","prop3.name"];
Below is my objects array
var objectArray = [
{"prop1":"prop1Data1","prop2":"prop2Data1","prop3":{"name":"Tom","age":"24","class":"graduate"},"prop4":"prop4Data1","prop5":"prop5Data1"},
{"prop1":"prop1Data2","prop2":"prop2Data2","prop3":{"name":"Cat","age":"24","class":"graduate"},"prop4":"prop4Data2","prop5":"prop5Data2"}
{"prop1":"prop1Data3","prop2":"prop2Data3","prop3":{"name":"Tom","age":"24","class":"graduate"},"prop4":"prop4Data3","prop5":"prop5Data3"}
{"prop1":"prop1Data4","prop2":"prop2Data4","prop3":{"name":"Tom","age":"24","class":"graduate"},"prop4":"prop4Data4","prop5":"prop5Data4"}
]
for( var item in objectArray ){
var objectArrayOnlySelectedProperties = _.pick(objectArray[item] , wantedPropArray);
}
suppose for first iteration lets see objectArrayOnlySelectedProperties data, I am getting
objectArrayOnlySelectedProperties = {"prop1":"prop1Data1","prop2":"prop2Data1"};
I am expecting it to give me the result something like this
objectArrayOnlySelectedProperties = {"prop1":"prop1Data1","prop2":"prop2Data1","prop3.name":"Tom"};
what i mean to say is _.pick method is not able to look into prop3 and get me prop3.name. Can anyone suggest how to use underscores' pick method to match the sub properties of each object in an array.
Thanks in advance
Upvotes: 4
Views: 13271
Reputation: 1
lodash has some great methods for checking for and setting deep object properties: has, set, & get. You can use these functions to build up your own deepPick / deepPluck function. Below is an ES6 style function that builds on lodash and uses the built in Array.reduce method. Just a note that lodash uses the dot delimiter for nested properties.
/**
* Deep pick / pluck properties.
*
* @param {object} the source object
* @param {array[string]} the properties to pick
*/
function deepPick (source, props) {
return props.reduce((result, key) => {
const exists = lodash.has(source, key);
if (exists) {
lodash.set(result, key, lodash.get(source, key));
}
return result;
}, {});
}
Upvotes: 0
Reputation: 3451
In case someone finds there way here. The _.pluck
function is what you want. Comes with underscore.
http://underscorejs.org/#pluck
Upvotes: 0
Reputation: 65795
I've created this plugin for underscore.js to help with problems like this.
Available at NPM and Bower
npm install deep_pick
bower install deep_pick
var input = {
one: 1,
two: true,
three: 'Three',
four: [1,2,3,4],
five: {
alpha: 1,
beta: 2,
gamma: 3,
teta: {
alef: 1,
beh: 2,
peh: 3
}
},
answer: '42.00',
description: 'This is an object.'
};
var schema = {
one: true,
three: true,
five: {
alpha: true,
teta: {
beh: true
}
}
};
deepPick(input, schema); // =>
{
one: 1,
three: "Three",
five: {
alpha: 1,
teta: {
beh: 2
}
}
}
Upvotes: 1
Reputation: 765
I've created a simple gist exactly for this: https://gist.github.com/peterslivka/9055188
_.mixin({
pickDeep: function(obj) {
var copy = {},
keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1));
this.each(keys, function(key) {
var subKeys = key.split('.');
key = subKeys.shift();
if (key in obj) {
// pick nested properties
if(subKeys.length>0) {
// extend property (if defined before)
if(copy[key]) {
_.extend(copy[key], _.pickDeep(obj[key], subKeys.join('.')));
}
else {
copy[key] = _.pickDeep(obj[key], subKeys.join('.'));
}
}
else {
copy[key] = obj[key];
}
}
});
return copy;
}
});
You can find working example here: http://jsfiddle.net/TFfHk/
Upvotes: 0
Reputation: 10603
It looks like this is not supported with underscorejs out of the box. But there is this gist that offers the support as a mix-in:
https://gist.github.com/furf/3208381
Here is some code using the above gist to do what you need: http://jsfiddle.net/wHXCv/1/
_.mixin({
deep: function (obj, key) {
var keys = key.split('.'),
i = 0,
value = null,
n = keys.length;
while ((obj = obj[keys[i++]]) != null && i < n) {};
value = i < n ? void 0 : obj;
var result = {};
result[key]=value;
return result;
}
});
var objectArray = [
{"prop1":"prop1Data1","prop2":"prop2Data1","prop3":{"name":"Tom","age":"24","class":"graduate"},"prop4":"prop4Data1","prop5":"prop5Data1"},
{"prop1":"prop1Data2","prop2":"prop2Data2","prop3":{"name":"Cat","age":"24","class":"graduate"},"prop4":"prop4Data2","prop5":"prop5Data2"},
{"prop1":"prop1Data3","prop2":"prop2Data3","prop3":{"name":"Tom","age":"24","class":"graduate"},"prop4":"prop4Data3","prop5":"prop5Data3"},
{"prop1":"prop1Data4","prop2":"prop2Data4","prop3":{"name":"Tom","age":"24","class":"graduate"},"prop4":"prop4Data4","prop5":"prop5Data4"}];
var plucked = function(o, wantedPropArray) {
return _.reduce(wantedPropArray, function(acc, val){
acc.push(_.deep(o,val));
return acc;
},[]);
}
var answer = _.map(objectArray, function(o){
return plucked(o, ["prop1","prop2","prop3.name"]);
});
console.log(JSON.stringify(answer));
Upvotes: 3
Reputation: 1856
I don't know about Underscore.js, but you may try this code:
function pick(obj,list){
var newObj={};
for(var i=0;i<list.length;i++){
var str=list[i].split('.');
var o=obj[str[0]];
for(var j=1;j<str.length;j++){
o=o[str[j]];
}
newObj[list[i]]=o;
}
return newObj;
}
Upvotes: 2