JS 基础! | 扁平数组和JSON树的转换

2,264 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

前言

这是一道工作中常用到的算法题~

你能学到

image.png

扁平数组 -> JSON 树

需求

你可能会得到类似这样的一个扁平数组,数组中的每一项都是一个对象,对象中有相关的逻辑结构的属性值~

let flatArr = [
	{ id: 1, title: "title1", parent_id: 0 },
	{ id: 2, title: "title2", parent_id: 0 },
	{ id: 3, title: "title2-1", parent_id: 2 },
	{ id: 4, title: "title3-1", parent_id: 3 },
	{ id: 5, title: "title4-1", parent_id: 4 },
	{ id: 6, title: "title3-2", parent_id: 3 },
];

效果

你需要的是根据其中的逻辑,获得一个 合理 的JSON树,其中的串联关系就要根据逻辑建立~
主要看那个parent_id
image.png

实现

结果数组

JSON 树形式,其实也是数组~

const result = [];

数组->map

先把数组转为 mapid作为 key,本身作为 value, 后面遍历匹配时就要靠这个 map 里的 id

const map = arr.reduce((pre, cur) => { 
	// key 就是 id,即 cur.id; value 为值本身
	pre[cur.id] = cur;
	return pre;
}, {}); // 传入初始值为 空对象{}

这里的 arr 是外面一层函数传入的参数,等下还要封装的

ok,我们现在就拿到了扁平数组的 map 形式
image.png

vscode 中查看代码运行

关于这个在 vscode 中查看代码运行的插件可以看这篇文章:vscode插件—— Quokka.js的简单使用

遍历 数组

使用 for of 遍历数组。

  • 父元素id为 0 的,那么就可以直接 push 到第一层,不需要其他的处理
  • 其余的就要找到对应的父元素,并push到父元素之下
for (let item of arr) {
		// 先找到父元素为 0 的,那么就可以直接 push 到第一层,不需要其他的处理
		if (item.parent_id === 0) {
			result.push(item);
			continue;
		}
		// 对于不是第一层的,我们就要先找到其父元素
		if (item.parent_id in map) {
			const parent = map[item.parent_id];
			(parent.children || (parent.children = [])).push(item); //这个简洁的方法
		}
	}

简洁初始化并操作

这个方法是我看源码的时候学的~

从mitt、tiny-emitter源码中学习手写订阅发布


全貌

ok,封装到函数中,并返回结果即可

const flatArrToJSONTree = arr => {
	const result = [];
	const map = arr.reduce((pre, cur) => {
		pre[cur.id] = cur;
		return pre;
	}, {}); 
	for (let item of arr) {
		if (item.parent_id === 0) {
			result.push(item);
			continue;
		}
		if (item.parent_id in map) {
			const parent = map[item.parent_id];
			(parent.children || (parent.children = [])).push(item);
		}
	}
	return result;
};

测试

插件数组中对象无法展开,所以赋值到控制台看看

const res = flatArrToJSONTree(flatArr);
console.log(res)

image.png


JSON 树 -> 扁平数组

需求

ok,除了上面的需求,有时我们可能也需要将 一个 JSON树形式的数组扁平化

效果

const res2 = JSONTreeToFlatArr(res);

image.png

实现

相比 数组转换为 JSON 树,JSON树转化为数组的代码量就少了很多,这里就不分段细说了

const JSONTreeToFlatArr = tree => {
	return tree.reduce((pre, cur) => {
		//解构拿出属性,并给 children 一个默认值
		const { children = [], ...rest } = cur;
		// concat 将每次结果都进行拼接
		return pre.concat([{ ...rest }], JSONTreeToFlatArr(children)); //递归处理 children
	}, []);
};

也是利用 reduce 这个方法,发现这个方法真是好用啊~
concat 拼接数组,再在里面递归处理~

测试

const res2 = JSONTreeToFlatArr(res);
console.log(res2);

image.png
大功告成~

学习资源

总结

文中措辞、知识点、格式如有疑问或建议,欢迎评论~你对我很重要~ 🌊如果有所帮助,欢迎点赞关注,一起进步⛵这对我很重要~