【问题标题】:Get path of an element inside a JSON object获取 JSON 对象内元素的路径
【发布时间】:2019-09-05 14:06:22
【问题描述】:

我有一个像下面这样的对象:

[
  {
    "uid": "aaa-aaa",
    "name": "foo",
    "children": []
  },
  {
    "uid": "aaa-bbb",
    "name": "bar",
    "children": [
      {
        "uid": "aaa-bbc",
        "name": "baz",
        "children": []
      },
      {
        "uid": "aaa-ccc",
        "name": "fooz",
        "children": [
          {
            "uid": "aaa-bcb",
            "name": "Yeah !",
            "children": []
          }
        ]
      }
    ]
  }
]

我正在尝试编写一个函数,该函数将该对象以uid 作为参数,并返回指向该对象中带有uid 的元素的路径(如果未找到,则返回null)。

类似这样的:

> getElementPath(bigObject, 'aaa-bcb')
[1, "children", 1, "children", 0]
or
> getElementPath(bigObject, 'aaa-bcb')
[1, 1, 0]

我知道函数必须是递归的,因为嵌套级别应该没有限制。我已经尝试过了,但它总是返回 null

function getElementPath (haystack, uid, currentPath = []) {
  if (haystack.uid === uid) {
    return currentPath
  }
  if (Array.isArray(haystack.children)) {
    for (let i = 0; i < haystack.children.length; i++) {
      let newPath = [...currentPath, i]
      let path = getElementPath(haystack.children[i], uid, newPath)
      if (path !== null) {
        return path
      }
    }
  }
  return null
}

【问题讨论】:

  • 如果您必须经常使用这个getElementPath() 函数,将数组缩减为一个对象一次是有意义的,这样您就可以直接访问任何元素。这可能会完全消除拥有完整路径的需要。
  • 您的“跟随对象”是一个数组。该数组作为haystack 传递给函数getElementPath,然后在第一个条件haystack.uid === uidhaystack 是一个数组,而在下一个条件下haystack.children 出于同样的原因未定义。剩下的唯一一个 return 语句最终返回 null。 ¯_(ツ)_/¯

标签: javascript json search


【解决方案1】:

我会使用flat

展平对象,然后遍历对象键,直到找到具有适当值的键。一旦找到,关键就是路径。

https://www.npmjs.com/package/flat

我的(天真而快速的)实现看起来像这样。但是我不喜欢它的是它知道查看“children”属性,如果您的数据结构定义明确并且不经常更改,那很好,flat 的想法无论如何都会起作用如果你改变你的数据结构。

getPathForUid = (uid,obj,thisPath = []) => {

    if(Array.isArray(obj)) {
        return obj.reduce((acc,item,idx) => getPathForUid(uid,item,thisPath.concat(idx)),[]);
    }

    return obj.uid === uid ? thisPath : getPathForUid(uid,obj.children,thisPath.concat('children'));

}

【讨论】:

  • 似乎是一个很好的解决方案,但如果可能的话,我希望不向我的项目添加依赖项(另外,我很好奇我的实现中出了什么问题)
  • 少写代码,多使用 small 库 - 你的代码永远不会像flat 那样经过(战斗)测试:) 我高度如果您正在做大量对象映射工作,推荐 flat(和一个配套库 - property-expr),就像我推荐 lodash 一样。
  • 这是编写更好(更快)软件的一般建议,但我的目标是自己成为更好的编码员。我有足够的时间花时间尝试调试我的实现,我来到这里寻求帮助,试图了解它有什么问题。请注意,我可能最终会使用flat,但当我能够编写我需要的函数时,我会感觉更好
  • 我发现我的情况有问题:主对象本身不应该是一个数组,它应该是一个包含 children 键的对象。
  • @KiJéy - 这是怎么回事? JSON.parse(JSON.stringify(currentPath)) 编辑:我明白了,你不想改变数组 - 你可以(应该)只做 const newPath = [...currentPath,i];
【解决方案2】:

试试这个:

    function getObject(listaJson, uid) {
    var object = null,
        param,
        type = null;

    if (listaJson.uid === uid) {
        return listaJson;
    }

    for (param in listaJson) {
        type = typeof(listaJson[param]);

        if (type.toString().toLowerCase() === 'object') {
            object = getObject(listaJson[param], uid);
        }

        if (object) {
            return object;
        }
    }

    return object;
}

console.log(getObject(json, 'aaa-aaa'));
console.log(getObject(json, 'aaa-bbb'));
console.log(getObject(json, 'aaa-bbc'));
console.log(getObject(json, 'aaa-ccc'));
console.log(getObject(json, 'aaa-bcb'));
console.log(getObject(json, 'aaa-xxx')); // null
console.log(getObject(json, 'yyy-jjj')); // null

【讨论】:

  • 我不想要对象而是对象的路径
猜你喜欢
  • 2020-07-18
  • 1970-01-01
  • 2021-05-31
  • 1970-01-01
  • 2016-10-12
  • 1970-01-01
  • 1970-01-01
  • 2012-08-01
  • 1970-01-01
相关资源
最近更新 更多