在深层对象中按名称查找属性

Sha*_*mal 39 javascript jquery lodash

我有一个巨大的收藏品,我正在寻找集合内某处的钥匙.获取包含该键/索引的所有对象的引用列表或完整路径的可靠方法是什么?我使用jQuery和lodash,如果它有帮助,你可以忘记无限指针递归,这是一个纯JSON响应.

fn({ 'a': 1, 'b': 2, 'c': {'d':{'e':7}}}, "d"); 
// [o.c]

fn({ 'a': 1, 'b': 2, 'c': {'d':{'e':7}}}, "e");
// [o.c.d]

fn({ 'aa': 1, 'bb': 2, 'cc': {'d':{'x':9}}, dd:{'d':{'y':9}}}, 'd');
// [o.cc,o.cc.dd]
Run Code Online (Sandbox Code Playgroud)

fwiw lodash有一个_.find函数,可以找到两个嵌套深度的嵌套对象,但之后似乎失败了.(例如http://codepen.io/anon/pen/bnqyh)

Ber*_*rgi 47

这应该这样做:

function fn(obj, key) {
    if (_.has(obj, key)) // or just (key in obj)
        return [obj];
    // elegant:
    return _.flatten(_.map(obj, function(v) {
        return typeof v == "object" ? fn(v, key) : [];
    }), true);

    // or efficient:
    var res = [];
    _.forEach(obj, function(v) {
        if (typeof v == "object" && (v = fn(v, key)).length)
            res.push.apply(res, v);
    });
    return res;
}
Run Code Online (Sandbox Code Playgroud)

  • 这几乎对我有用.我不得不将第3行更改为`return [obj [key]];`而不是让我得到一个键值的数组而不是包装对象 (3认同)
  • @ChrisMontgomery:是的,但OP想要"所有对象*包含*那个键"(可能他正在对结果做一个'pluck()`) (2认同)

Eug*_*nko 24

纯JavaScript解决方案如下所示:

function findNested(obj, key, memo) {
  var i,
      proto = Object.prototype,
      ts = proto.toString,
      hasOwn = proto.hasOwnProperty.bind(obj);

  if ('[object Array]' !== ts.call(memo)) memo = [];

  for (i in obj) {
    if (hasOwn(i)) {
      if (i === key) {
        memo.push(obj[i]);
      } else if ('[object Array]' === ts.call(obj[i]) || '[object Object]' === ts.call(obj[i])) {
        findNested(obj[i], key, memo);
      }
    }
  }

  return memo;
}
Run Code Online (Sandbox Code Playgroud)

这是你如何使用这个功能:

findNested({'aa': 1, 'bb': 2, 'cc': {'d':{'x':9}}, dd:{'d':{'y':9}}}, 'd');
Run Code Online (Sandbox Code Playgroud)

结果将是:

[{x: 9}, {y: 9}]
Run Code Online (Sandbox Code Playgroud)

  • @ChrisMontgomery,这是因为原始问题仅包含对象,并且没有任何数组,所以我更新了示例。 (2认同)

小智 5

这将在对象(hay)的数组中深度搜索值(needle),然后返回包含结果的数组...

search = function(hay, needle, accumulator) {
  var accumulator = accumulator || [];
  if (typeof hay == 'object') {
    for (var i in hay) {
      search(hay[i], needle, accumulator) == true ? accumulator.push(hay) : 1;
    }
  }
  return new RegExp(needle).test(hay) || accumulator;
}
Run Code Online (Sandbox Code Playgroud)