javascript - 在 JavaScript 中通过键从嵌套对象数组中查找对象

标签 javascript object recursion

我有一个像这样的 JSON 嵌套对象树。 如何通过将 ID 值传递给函数来获取指定的对象。 (ID是所有嵌套对象中的key)

我尝试使用递归和 JSON.stringify().findObject() 但不知何故它们不起作用。

{
    "id": "A",
    "name": "Item A",
    "child": [
        {
            "id": "B",
            "name": "Item B",
            "child": [
                {
                    "id": "C",
                    "name": "Item C"
                    "child": []
                }
            ]
        },
        {
            "id": "D",
            "name": "Item D",
            "child": []
        }
    ]
}


//Calling like this
var result = findObject("C");

然后console.log(result);应该是

{
  "id": "C",
  "name": "Item C"
  "child": []
}

最佳答案

Nick Parsons 的回答很棒,代码写得很好,解释也很好。

但我认为有可能把它写得更通用、更简单。

虽然这里的要求是通过id进行搜索,但我们可以很容易地想象出我们想要匹配的各种其他方式。我们可以编写一个采用任意谓词的通用版本,然后使用一个简单的函数对其进行配置,而不是试图预测所有这些。

这是一种方法:

const deepFind = (pred) => ([x, ...xs] = []) => 
  x && (pred (x) ? x : deepFind (pred) (x.child) || deepFind (pred) (xs))

const findById = (id) => (obj) =>  
  deepFind ((o) => o.id == id) ([obj])

const input = {id: "A", name: "Item A", child: [{id: "B", name: "Item B", child: [{id: "C", name: "Item C", child: []}]}, {id: "D", name: "Item D", child: []}]};

console .log ('C:', findById ('C') (input)) //~> {id: "C", name: "Item C", child: []}
console .log ('X:', findById ('X') (input)) //~> undefined

deepFind 接受谓词函数并返回一个函数,该函数接受数组并在深度优先搜索时返回第一个匹配项(在 node -> node.child 树上) 匹配谓词。

我们用 findById 包装它,它接受一个目标 id,并返回一个函数,该函数接受一个输入对象,将该对象包装在一个数组中,并调用 deepFind用于测试 id 是否与目标和该数组匹配的谓词。

我们可以通过向 deepFind 添加另一个初始参数来告诉我们树的结构,从而轻松地使其更通用。 (node -> node.children 可能更常见。)但这是另一天的任务。

deepFind 可能有一个稍微密集的实现。它可以用多种方式编写,如果其中一种对您更有意义的话:

const deepFind = (pred) => (xs) => {
  for (let x of xs) {
    if (pred (x)) {return x}
    return deepFind (pred) (x .child || [])
  }
}

const deepFind = (pred) => ([x, ...xs]) => 
  x == undefined
    ? undefined
    : pred (x) 
      ? x
      : deepFind (pred) (x.child || []) || deepFind (pred) (xs)

或在 traverse 生成器函数之上:

function * traverse (xs = []) {
  for (let x of xs) {
    yield x;
    yield * traverse (x.child || [])
  }
}

const deepFind = (pred) => (obj) => {
  for (let node of traverse ([obj])) {
    if (pred (node)) {return node} 
  }
}

我们还可以找到更多。

关于javascript - 在 JavaScript 中通过键从嵌套对象数组中查找对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68559392/

相关文章:

javascript - 如何在angularjs中替换PDF.js?

javascript - 查找由两个 3 位数乘积组成的最大回文数 - Javascript

javascript - 在node.js中使用es6类有用吗?

c++ - 在 C++ 中从二叉搜索树(递归)复制叶子

c++ - 查找一棵树是否为单声道(所有元素都是唯一的)的函数?

algorithm - 使用递归方法查找接近路径或区域

javascript - 可以将 Catch block 留空导致 JavaScript 中的问题

javascript - 对象声明 : Do strings as keys make a difference?

java - 获取所有行 SQLite Android Studio

javascript - 检查键是否不存在或应在过滤方法中具有特定值