javascript - 如何在 Javascript 中将方法转换为递归函数?

标签 javascript vue.js cytoscape.js

我从点之前的“res”数据的第一个键创建了一个子菜单。在这个子菜单中,我只在“res”数据中显示了一次具有相同名称的键。即:“用户”、“部门”和“项目”仅显示为子菜单项。但是当我点击它们时,其他同名的键不会出现一次。例如:当我点击“项目”项时,打开了 5 个“类型”子菜单。我也需要为“id”键做同样的事情。我该如何解决这个问题?

var res = {
    "user.name.firstname": "firstname",
    "user.name.lastname": "lastname",
    "department.id1": 1,
    "department.id2": 2,
    "project.name": "project",
    "project.type.name": "project1",
    "project.type.id.first3": "321",
    "project.type.id.last3" : "789",
    "project.type.id.abc": "abc",

}
var myList = []
var myFinalList = []

Object.keys(res).forEach(key => {
    var subMenus = key.split(".")
    subMenus.forEach(subMenu => {
        var newObject = {}
        newObject["id"] = subMenu
        newObject["content"] = subMenu

        myList.push(newObject)
    })
    for (var i = myList.length - 1; i >= 0; i--) {
        if (i - 1 !== -1) {
            //console.log(i - 1)
            myList[i - 1]["submenu"] = [myList[i]]
        }
    }
    myFinalList.push(myList[0])
    //console.log(myList)
    myList = []
})
var mySet = new Set()
myFinalList.forEach(obj => {
    mySet.add(obj["id"])
})
    var veryFinalList = []
    mySet.forEach(key => {
        var eachKeyObject = myFinalList.filter(sub => sub.id === key)

        var sourceObject = eachKeyObject[0]
        if(eachKeyObject.length > 1){
            for(var i = 1; i < eachKeyObject.length; i++){
                sourceObject["submenu"] = sourceObject["submenu"].concat(eachKeyObject[i]["submenu"])
            }
        }
        veryFinalList.push(sourceObject)
        console.log(veryFinalList)
    })

我的输出应该是这样的:

output= {
    "user": {
        "name": {
            "firstname": "firstname",
            "lastname": "lastname",
        }
    },
    "department": {
        "id1":1,
        "id2":2,
    },
    "project": {
        "name": "project",
        "type": {
            "name": "project1",
            "id": {
                "first3": "321",
                "last3" : "789",
                "abc" : "abc"
            }
        }
    }
}

最佳答案

给你:

var res = {
    "user.name.firstname": "firstname",
    "user.name.lastname": "lastname",
    "department.id1": 1,
    "department.id2": 2,
    "project.name": "project",
    "project.type.name": "project1",
    "project.type.id.first3": "321",
    "project.type.id.last3" : "789",
    "project.type.id.abc": "abc",

}

let finalObj = { };

for(let key in res) {
  let value = res[key];
  let keyArr = key.split('.');

  // Magic happens here (https://stackoverflow.com/a/68860247/2284136)
  keyArr.reduce((acc, key, i) => {
  
    if (i < keyArr.length - 1) {
      if (!acc[key]) acc[key] = {};
    } 
    else {
      acc[key] = value;
    }

    return acc[key];
  }, finalObj)
}

console.log(finalObj);

我用了this answer对于 reduce 实现,它允许我们将数据深入到对象路径中。我们只需要首先将键拆分为数组,例如 "user.name.firstname"=> ["user", "name", "firstname"] 并将其提供给 使用 res["user.name.firstname"] 的值 reduce 函数。

关于您关于“将方法转换为递归函数”的实际问题,我一开始确实尝试过类似的方法,直到我意识到我们不需要在这里这样做。

另外,为了将来的引用,虽然递归函数对于某些特定问题非常有用,但一般的经验法则是避免在非绝对必要时使用它们。它们难以阅读和理解,难以调试,并可能导致各种古怪的问题。

关于您为解决此问题所做的尝试。我认为这是一个很好的尝试,这正是一个伟大的程序员在遇到麻烦时应该做的!我喜欢阅读这样的代码,因为我可以看到您在尝试解决问题时陷入的挫败感。虽然这确实非常令人沮丧,但它也同样是一次很好的学习经历。我个人认为,当你发现自己从那个洞的底部,仍然没有解决方案时,那就是寻求帮助的最佳时机,就像你一样!

关于javascript - 如何在 Javascript 中将方法转换为递归函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72647078/

相关文章:

javascript - 有没有办法将 v-for 中的对象属性传递给 Vue 数据?

cytoscape.js - 在 cytoscape.js 中导出选定的节点和边

javascript - 如何检查元素是否隐藏在 jQuery 中?

javascript - 以编程方式获取当前页面中的所有 javascript 代码

javascript - 文本丢失样式(即使 css 显示它应该具有它),但如果代码在控制台上单步执行(包括 jsfiddles),则不会丢失样式

laravel - 如何在组件的方法中访问 Vue JS Prop ?

javascript - jqgrid 寻呼机在插入新网站时失去良好的风格

javascript - dc.js Vue 渲染图表不正确

javascript - Cytoscape - 不要将映射分配给没有相应数据的元素

javascript - Cytoscape.js:将渲染位置转换为模型位置