获取嵌套值的路径

问题描述 投票:1回答:3

我认为这必须是一个副本,但我无法在SO上找到它。鉴于这样的对象:

let obj = { keyA: { keyB: 'hi', keyC: { keyD: null } }, keyE: 'hi' }

有没有办法找到给定值的关键路径,如下所示:

keyPaths(obj, 'hi') // -> [ 'keyA.keyB', 'keyE' ]
keyPaths(obj)       // -> [ 'keyA.keyB.keyD' ]

我试图调整一些能够找到知识密钥的深层值的答案,而我几乎能够适应this one that finds deep nulls,但我无法弄清楚如何获得路径,而不仅仅是最深的密钥。

javascript
3个回答
2
投票

我会像这样深度搜索:

let obj = { keyA: { keyB: 'hi', keyC: { keyD: null } }, keyE: 'hi' }

function keyPaths(parent, value = null, chain) {
  let allResults = [];
  for (const prop in parent) {
    if (parent.hasOwnProperty(prop)) {
      const element = parent[prop];
      const newChain = chain ? chain + '.' + prop : prop;
      if (element === value) {
        allResults.push(newChain);
      }
      else if (Object.keys(prop).length > 1) {
        allResults = [...allResults, ...keyPaths(element, value, newChain)];
      }
    }
  }
  return allResults;
}

console.log(keyPaths(obj, 'hi')) // -> [ 'keyA.keyB', 'keyE' ]
console.log(keyPaths(obj))       // -> [ 'keyA.keyB.keyC' ]

基本上,我检查给定元素的所有属性以获得匹配值。如果属性与值不匹配,但具有子属性,则递归调用该函数,并合并调用迭代和递归调用的结果。


2
投票

通过在递归函数中使用reduce,您可以非常干净地完成此操作。该函数将返回一个数组,您可以将map()返回到您想要的任何字符串值。

let obj = { keyA: { keyB: 'hi', keyC: { keyD: null } }, keyE: 'hi' }

function keyPaths(obj, val, path = [] ){
  if (!obj) return 
  return Object.entries(obj).reduce((res, [k, v]) => {
    let p = [...path, k]
    if (v == val) res.push(p)
    else if (v && typeof v == 'object') res.push(...keyPaths(v, val, p))
    return res
  }, [])
}

console.log(keyPaths(obj, 'hi').map(a => a.join('.')))
console.log(keyPaths(obj).map(a => a.join('|')))

0
投票

如果可以使用Lodash + Deepdash,那么:

let paths = _(obj).filterDeep((v)=>v=='hi').paths().value();

Codepen is here

© www.soinside.com 2019 - 2024. All rights reserved.