如何在键为字符串值为数组的Map中包含父节点(JavaScript)
问题:遍历树结构构建父节点Map时数组值被覆盖
我尝试遍历一棵树木并创建一个Map数据结构,用于存储元素的父节点列表,格式为键{子元素名称}:值{父节点名称数组}。
我的代码如下:
global.parentMap = new Map() function readTree(root) { let queue = [root]; while (queue.length > 0) { let node = queue.shift(); for (let childType in node.children) { for (let child of node.children[childType]) { let newChild = {...child}; queue.push(newChild); if(global.parentMap.has(newChild.item.name)){ global.parentMap.set(newChild.item.name,global.parentMap.get(newChild.item.name).push(node.item.name))} if(!parentMap.has(newChild)){ global.parentMap.set(newChild.item.name,[]); } console.log("Parent"+node.item.name+" has childs "+newChild.item.name) global.parentMap.get(newChild.item.name).push(node.item.name); } } } }
问题在于新的父节点无法被推入Map的数组值中,总是被覆盖。控制台输出如下:
Parent: testing_group has childs:command_name Parent: agv_commands has childs:location_name Parent: agv_commands has childs:header_frame_id Parent: agv_commands has childs:location_coordinates Parent: agv_commands has childs:robot_name Parent: agv_commands has childs:load_id Parent: agv_commands has childs:command_item Parent: agv_commands has childs:command_name Map(7) { 'command_name' => [ 'agv_commands' ], // 本应包含testing_group 'location_name' => [ 'agv_commands' ], 'header_frame_id' => [ 'agv_commands' ], 'location_coordinates' => [ 'agv_commands' ], 'robot_name' => [ 'agv_commands' ], 'load_id' => [ 'agv_commands' ], 'command_item' => [ 'agv_commands' ] }
问题分析与修复
错误原因:
push返回值误用:global.parentMap.get(...).push(...)中,push方法返回的是数组的新长度,不是数组本身。你用set把这个长度存进Map,导致后续操作完全错误。- 判断条件错误:
if(!parentMap.has(newChild))判断的是newChild对象,但Map的键是子元素名称字符串,应该判断!global.parentMap.has(newChild.item.name),而且这个判断的顺序也不对。 - 重复执行
push:代码里先在if里执行了一次push(虽然逻辑错了),后面又重复push,导致逻辑混乱。
修复后的代码:
global.parentMap = new Map() function readTree(root) { let queue = [root]; while (queue.length > 0) { let node = queue.shift(); for (let childType in node.children) { for (let child of node.children[childType]) { let newChild = {...child}; queue.push(newChild); const childName = newChild.item.name; const parentName = node.item.name; // 先初始化空数组(如果子节点还没在Map里) if (!global.parentMap.has(childName)) { global.parentMap.set(childName, []); } // 直接向数组添加父节点,数组是引用类型,修改后Map里的值会同步更新 global.parentMap.get(childName).push(parentName); console.log(`Parent: ${parentName} has childs: ${childName}`); } } } }
修复说明:
- 移除了错误的
set操作:因为数组是引用类型,直接get到数组后执行push,Map里的数组会自动更新,不需要重新set。 - 修正了初始化数组的判断条件:确保针对子元素名称判断,且在添加父节点前完成初始化。
- 删除了重复的
push操作,避免冗余逻辑。 - 用模板字符串优化了日志输出,可读性更强。
修复后,command_name对应的数组会正确包含['testing_group', 'agv_commands'],符合预期。
内容的提问来源于stack exchange,提问作者Θοδωρής Σουλτανόπουλος
相关产品推荐
相关产品推荐

