保证数据一致性,先生成4000条json数据到本地,然后分别读取文本执行处理
node代码
node是用midway框架
forNum1:number = 0
forNum2:number = 0
//执行测试
async index(){
// 生成菜单列表
// const menuList = await this.generateMenuList([], 4000);
const menuListStr = fs.readFileSync(this.app.getAppDir()+'/public/listJson.txt', 'utf8');
const menuList = JSON.parse(menuListStr)
console.time("4000条 引用类型 时间:deepTree");
await this.deepTree(menuList);
console.log("4000条 引用类型 时间:")
console.timeEnd("4000条 引用类型 时间:deepTree");
console.log("循环次数",this.forNum1)
// this.logger.info("deepTree 数据", JSON.stringify(l));
console.time("4000条 递归 时间:deepTree2");
await this.deepTree2(menuList, null);
console.timeEnd("4000条 递归 时间:deepTree2");
console.log("循环次数",this.forNum2)
}
// 列表转树形
async deepTree(list: any[]){
const newList: any[] = [];
const map: any = {};
for (let index = 0; index < list.length; index++) {
this.forNum1++
const e = list[index];
map[e.id] = e;
}
for (let index = 0; index < list.length; index++) {
this.forNum1++
const e = list[index];
const parent = map[e.parentId];
if (parent) {
(parent.children || (parent.children = [])).push(e);
} else {
newList.push(e);
}
}
return newList;
}
// 递归遍历
async deepTree2(arr: any[], parentId: any) {
// const loop = (parentId: any) => {
// return arr.reduce((pre, cur) => {
// this.forNum2++
// if (cur.parentId == parentId) {
// cur.children = loop(cur.id);
// pre.push(cur);
// }
// return pre;
// }, []);
// }
const list = []
const loop = (parentId: any)=>{
for (let index = 0; index < arr.length; index++) {
this.forNum2++
if (arr[index].parentId == parentId) {
arr[index].children = loop(arr[index].id);
list.push(arr[index]);
}
}
return list
}
return loop(parentId);
}
//生成随机的菜单列表数据,给转换树形菜单使用
async generateMenuList(
menuList: { id: number; parentId: number | null }[] = [],
maxDepth: number = 5
){
// 如果菜单列表长度达到1000,则停止生成
if (menuList.length > maxDepth || menuList.length >= 10000) {
return menuList;
}
const nextID = menuList.length + 1
// 如果菜单列表不为空,则随机选择一个已存在的id作为parentId;否则parentId为null
let parentId: number | null = null;
if (menuList.length > 0) {
parentId = menuList[Math.floor(Math.random() * menuList.length)].id;
}
// 将新菜单项添加到列表中
menuList.push({ id:nextID, parentId });
// 递归调用生成子菜单项,深度加1
return this.generateMenuList( menuList, maxDepth);
}
测试结果
go代码
go框架是goframe
var (
ctx context.Context
forNum1 = 0
forNum2 = 0
)
type MenuItem struct {
ID *int `json:"id"` // 节点的唯一标识符
ParentId *int `json:"parentId"` // 父节点的ID
Children []*MenuItem `json:"children"` // 子节点列表
}
// 遍历树
func DeepTree(strSlice []*MenuItem) interface{} {
var (
strMap = make(map[int]*MenuItem)
newList []*MenuItem
)
for i := range strSlice {
node := strSlice[i]
strMap[*node.ID] = node
forNum1++
}
for i := range strSlice {
node := strSlice[i]
if node.ParentId != nil {
strMap[*node.ParentId].Children = append(strMap[*node.ParentId].Children, node)
} else {
newList = append(newList, node)
}
forNum1++
}
return newList
}
// 执行递归
func DeepTree2(strSlice []*MenuItem) interface{} {
newList := loop(strSlice, 0)
return newList
}
// 递归遍历树
func loop(strSlice []*MenuItem, parentId int) []*MenuItem {
var newList []*MenuItem
for i := range strSlice {
forNum2++
if parentId == 0 {
if strSlice[i].ParentId == nil {
strSlice[i].Children = loop(strSlice, *(strSlice[i].ID))
newList = append(newList, strSlice[i])
}
} else if strSlice[i].ParentId != nil && *(strSlice[i].ParentId) == parentId {
strSlice[i].Children = loop(strSlice, *(strSlice[i].ID))
newList = append(newList, strSlice[i])
}
}
return newList
}
// 生成随机菜单列表数据
func generateMenuList(menuList []*MenuItem, maxDepth int) []*MenuItem {
// 如果菜单列表长度达到10000,则停止生成
if len(menuList) >= maxDepth || len(menuList) >= 10000 {
return menuList
}
nextID := len(menuList) + 1
// 如果菜单列表不为空,则随机选择一个已存在的id作为parentId;否则parentId为nil
var parentId *int
if len(menuList) > 0 {
existingItem := menuList[rand.Intn(len(menuList))]
parentId = existingItem.ID
}
// 将新菜单项添加到列表中
menuList = append(menuList, &MenuItem{ID: &nextID, ParentId: parentId})
// 递归调用生成子菜单项,深度加1
return generateMenuList(menuList, maxDepth)
}
开始测试
func Test(t *testing.T) {
var (
menuSlice []*MenuItem
)
//menuSlice1 = generateMenuList([]*MenuItem{}, 15)
//gfile.PutContents("./listJson-15.txt", gconv.String(menuSlice1))
jsonStr := gfile.GetContents("./listJson.txt")
err := gconv.Scan(jsonStr, &menuSlice)
if err != nil {
return
}
startTime1 := time.Now()
DeepTree(menuSlice)
endTime1 := time.Now()
g.Log().Debugf(ctx, "4000条 引用类型 时间:%v,循环次数:%d", endTime1.Sub(startTime1), forNum1)
startTime2 := time.Now()
DeepTree2(menuSlice)
endTime2 := time.Now()
g.Log().Debugf(ctx, "4000条 递归 时间:%v,循环次数:%d", endTime2.Sub(startTime2), forNum2)
}
测试结果:
测试连续10次的数据