_.pick方法匹配对象数组中的子属性

时间:2013-03-05 11:21:51

标签: javascript underscore.js

我正在以下列方式使用_.pick方法

假设我有一个字符串数组,这些字符串只是我希望从对象数组中的每个对象获取的属性名称

var wantedPropArray=["prop1","prop2","prop3.name"];

下面是我的对象数组

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

假设第一次迭代让我们看到objectArrayOnlySelectedProperties数据, 我正在

objectArrayOnlySelectedProperties = {"prop1":"prop1Data1","prop2":"prop2Data1"};

我希望它能给我这样的结果

objectArrayOnlySelectedProperties = {"prop1":"prop1Data1","prop2":"prop2Data1","prop3.name":"Tom"};

我的意思是_.pick方法无法查看prop3并得到prop3.name。 任何人都可以建议如何使用下划线的pick方法来匹配数组中每个对象的子属性。

提前致谢

6 个答案:

答案 0 :(得分:3)

看起来开箱即用的下划线不支持此功能。但是有这个要点作为混合提供支持:

https://gist.github.com/furf/3208381

以下是一些使用上述要点的代码来执行您所需的操作: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));

答案 1 :(得分:2)

我不知道Underscore.js,但你可以试试这段代码:

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

答案 2 :(得分:1)

下划线深度选择插件

我为underscore.js创建了这个插件来帮助解决这类问题。

Deep Pick Pluging

可在NPM和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
    }
  }
}

答案 3 :(得分:0)

我为此创造了一个简单的要点: 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;
    }
});

您可以在此处找到工作示例:http://jsfiddle.net/TFfHk/

答案 4 :(得分:0)

如果有人在这里找到了方法。 _.pluck函数就是您想要的。附带下划线。

http://underscorejs.org/#pluck

答案 5 :(得分:0)

lodash有一些检查和设置深层对象属性的好方法:has,set,&amp;得到。您可以使用这些函数来构建自己的deepPick / deepPluck函数。下面是一个ES6样式函数,它基于lodash并使用内置的Array.reduce方法。请注意,lodash使用嵌套属性的点分隔符。

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