javascript 如何递归循环访问特定键的嵌套对象

yws3nbqq  于 2023-02-02  发布在  Java
关注(0)|答案(2)|浏览(144)

我正在尝试写一个递归函数,它本质上是向下钻取一个对象,寻找一个特定的键。一旦找到那个键,我想重命名那个对象键,保留原来的内容,并继续迭代找到的键值(对象数组),寻找相同的键(如果存在的话)。

const data = {
   "name": "lorem",
   "folders": [
      {
         "name": "ipsum",
         "folders": [
            {
               "name": "inner ipsum",
               "folders": [
                   {
                      "name": "first nested"
                   },
                   {
                      "name": "second nested" 
                   }
               ]
            }
         ]
      },
      {
         "name": "dolor",
         "folders": [
            {
               "name": "first inner dolor"
            },
            {
               "name": "second inner dolor",
               "folders": [
                  {
                     "name": "test"
                  }
               ]
            }
         ]
      }
   ]
   
}

// recursive function that looks for key === "folders" within obj and renames to "items"
// continues to search within "items" value for the same "folders" key to repeat the process of // renaming the obj

const recursivelyGetAllFolders = (obj) => {
   for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        if (key === "folders") {
          // keep contents of folders obj, but rename key to "items"
          obj["items"] = obj["folders"];

          // call function recursively to iterate through again?
          if (obj["items"] && typeof obj["items"] === "object") {
            const result = recursivelyGetAllFolders(folder["items"]);
            if (result) {
               return result;
            }
          } else {
              return obj;
          }
        }
      }
    }
}

recursivelyGetAllFolders(data);
jutyujz0

jutyujz01#

你不需要遍历object的键。你只需要

  • 检查对象是否有folders键,并将其重命名为items
  • 然后递归调用items每个对象上的函数(递归调用items数组本身,而不是数组中的每个对象)
function recursivelyUpdateFolders(obj) {
  if (obj.hasOwnProperty("folders")) {
    obj.items = obj.folders
    delete obj.folders
    obj.items?.forEach(recursivelyUpdateFolders)
  }
  return obj
}

下面是一个片段:

const data={name:"lorem",folders:[{name:"ipsum",folders:[{name:"inner ipsum",folders:[{name:"first nested"},{name:"second nested"}]}]},{name:"dolor",folders:[{name:"first inner dolor"},{name:"second inner dolor",folders:[{name:"test"}]}]}]};

function recursivelyUpdateFolders(obj) {
  if (obj.hasOwnProperty("folders")) {
    obj.items = obj.folders
    delete obj.folders
    obj.items?.forEach(recursivelyUpdateFolders)
  }
  return obj
}

console.log(
  recursivelyUpdateFolders(data)
)
e5nqia27

e5nqia272#

我们可以退一步,将"folders"和"items"参数设置为函数,这不会增加代码的难度,反而会使代码更加灵活。
这个版本不会改变你的原始版本(我们不是野蛮人,对吗?),但会返回一个应用了更改的副本。

const renameNestedKey = (source, target) => (o) =>
  Array .isArray (o) 
    ? o .map (renameNestedKey (source, target))
  : Object (o) === o
    ? Object .fromEntries (Object .entries (o) .map (
        ([k, v]) => [k == source ? target : k, renameNestedKey (source, target) (v)] 
      ))
  : o

const data = {name: "lorem", folders: [{name: "ipsum", folders: [{name: "inner ipsum", folders: [{name: "first nested"}, {name: "second nested"}]}]}, {name: "dolor", folders: [{name: "first inner dolor"}, {name: "second inner dolor", folders: [{name: "test"}]}]}]}

console .log (renameNestedKey ('folders', 'items') (data))
.as-console-wrapper {max-height: 100% !important; top: 0}

我们的函数接受源键值名和目标键值名,并返回一个接受输入对象的函数。当输入是一个数组时,它在该数组上map自身。当输入是一个对象时,我们将其拆分为键值对,然后在这些键值对上Map,必要时转换键值,并在值上循环。然后把得到的键值对放回一个对象中。当输入既不是数组也不是对象时,我们就简单地返回它。

相关问题