4

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

6 Answers 6

3

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));
Sign up to request clarification or add additional context in comments.

8 Comments

the links you gave are good,but is it possible that i can get both the keys and values instead of only values, I mean basically i want the same object,but with only selected properties.
@bhargav,I tidied it up a bit more - the earlier solution was annoying me:)
i dont want to use the plucked solution, i want to get the sub properties as separate items,like [{"prop3.name":"tom","prop3.age":"24"},{"prop3.name":"cat","prop3.age":"25"}]
currently i am getting like this [{"prop3":{"name":"tom","age":"24"}},{"prop3":{"name":"cat","age":"25"}}]
so you want to flatten the structure? you just want a flat array of objects containing the wanted properties?
|
2

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;
}

Comments

1

Underscore Deep Pick Plugin

I've created this plugin for underscore.js to help with problems like this.

Deep Pick Pluging

Available at NPM and Bower

npm install deep_pick
bower install deep_pick

Example:

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
    }
  }
}

Comments

0

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/

Comments

0

In case someone finds there way here. The _.pluck function is what you want. Comes with underscore.

http://underscorejs.org/#pluck

Comments

0

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;
  }, {});
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.