查找对象中与给定字符串匹配的所有键的路径

时间:2018-10-16 09:58:41

标签: javascript ecmascript-6

我有一个对象,在各个深度都有重复的键名。我想编写一个函数(普通JS),该函数返回与给定名称匹配的所有键的路径数组。

例如:

const obj = {
    stuff: {
        A: 'text'
    },
    deeperStuff: {
        nested: {
            A: ['data']
        }
    }
};

const func = (object, key) => {
    ...
};

console.log(func(obj, 'A'));
// [['stuff', 'A'], ['deeperStuff', 'nested', 'A']]

很抱歉,如果这是一个重复的问题,但我找不到适合我需要的答案。

预先感谢

P

3 个答案:

答案 0 :(得分:2)

这样的事情怎么样...拿住对象并遍历其键以寻找匹配项。如果找到一个,则添加到哈希(我更改了输出类型)。如果值是另一个对象,则使用该嵌套对象递归。

const myObj = {
    stuff: {
        A: 'text'
    },
    deeperStuff: {
        nested: {
            A: ['data']
        }
    }
};

function findKeys(obj, desiredKey, path = [], results = {}) {
  const keys = Object.keys(obj)
  keys.forEach(function(key) {
    const currentPath = path.concat([key])
    if (key === desiredKey) {
      results[currentPath.join('/')] = obj[key]
    } 
    if (typeof obj[key] === "object") {
      findKeys(obj[key], desiredKey, currentPath, results)
    }
  })
  return results
}

// same functionality with your desired return type
function findKeyArray(obj, desiredKey, path = [], results = []) {
  const keys = Object.keys(obj)
  keys.forEach(function(key) {
    const currentPath = path.concat([key])
    if (key === desiredKey) {
      results.push(currentPath); // changed this line
    } 
    if (typeof obj[key] === "object") {
      findKeyArray(obj[key], desiredKey, currentPath, results); // and this line ;)
    }
  })
  return results
}

console.log(findKeys(myObj, "A"))
console.log(findKeyArray(myObj, "A"))

输出

{
  deeperStuff/nested/A: ["data"],
  stuff/A: "text"
}

[["stuff", "A"], ["deeperStuff", "nested", "A"]]

答案 1 :(得分:1)

您可以使用迭代和递归方法,而无需存储结果的实际访问路径。

function getDeeperPath(object, key) {
    return Object
        .entries(object)
        .reduce((r, [k, v]) => {
            if (k === key) {
                return r.concat(k);
            }
            if (v && typeof v === 'object') {
                getDeeperPath(v, key).forEach(t => r.push([k, ...t]));
            }
            return r;
        }, []);
}

const object = { stuff: { A: 'text' }, deeperStuff: { nested: { A: ['data'] } } };

console.log(getDeeperPath(object, 'A'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:0)

这是一个使用 object-scan 的解决方案。简洁并允许在搜索路径中使用复杂的模式,但您正在添加依赖项 - 因此这里需要权衡。

// const objectScan = require('object-scan');

const myObj = { stuff: { A: 'text' }, deeperStuff: { nested: { A: ['data'] } } };

console.log(objectScan(['**.A'])(myObj));
// => [ [ 'deeperStuff', 'nested', 'A' ], [ 'stuff', 'A' ] ]

console.log(objectScan(['**.stuff.A'])(myObj));
// => [ [ 'stuff', 'A' ] ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.8.0"></script>

免责声明:我是object-scan

的作者