对象扁平化处理传送门
看我这一篇 juejin.cn/post/721586…
反对象扁平化
实现一个函数 unflatten,将以下扁平化后的对象还原为 output 对象
var input = {
"a": 1,
"b[0]": 1,
"b[1]": 2,
"b[2].c": true,
"b[3][0]": 3,
"d.e": 2,
"d.f.e.g": 3,
"e.j": 222,
"e.k[0]": 1,
"e.k[1]": 2,
"e.k[2]": 3,
"e.k[3].d": 32,
"josie": "so cool"
}
var output = {
a: 1,
b: [ 1, 2, { c: true }, [ 3 ] ],
d: { e: 2, f: 3 },
g: null,
e: {j: 222, k: [1,2,3,{a: null, d:32}]},
f: undefined,
h: '',
josie: 'so cool'
}
解题思路
- 将input对象遍历拿到所有key值存储在一个数组中flattenKeyArr
- 遍历flattenKeyArr,对每一项key进行反扁平化还原
- 根据
/\.?([^.\[\]]+)$|\[(\d+)\]$/正则规则匹配出包含.或[]的key值字符串,再通过slice截取出真正的key - 根据拿到的这一层级的key,去从data中获取value a. 如果没有的话,说明当前key值存在子节点,那么需要将其push到flattenKeyArr中,继续遍历查找。 b. 如果找到value的话,就将其赋值给target
- 每一轮循环后,target都会存入当前这个key的值(说实话这里的写法有点不太好理解,我理解为绑定引用,这样target和result就绑定了,看明白的同学可以评论区点评下)
代码
参考网上某大佬写的,稍微改了一点点
const unflatten = (data) => {
// 非基础类型return
if (Object(data) !== data || Array.isArray(data)) {
return data;
}
const regex = /\.?([^.\[\]]+)$|\[(\d+)\]$/;
const flattenKeyArr = Object.keys(data);
let result, p;
while ((p = flattenKeyArr.shift())) { // 循环一遍取出一个,改变原数组
const match = regex.exec(p);
// match[2]的值意为具体取到[]里面的数字,数组类型取[2],对象类型取[1]
const arrayItem = match[2]
const objItem = match[1]
const newData = arrayItem ? [] : {};
let target;
// 存在子节点(因为 .[ 不会在第一个,所有可以这么判断)
if (match.index) {
// 截取出匹配过的key值
const key = p.slice(0, match.index);
// data中不存在这个key,说明还有子节点
if (!(key in data)) {
// 赋值空类型,方便后面添加属性
data[key] = newData;
flattenKeyArr.push(key);
}
// 绑定引用
target = data[key];
} else {
if (!result) {
result = newData;
}
// 绑定引用,秒啊
target = result
}
// 每轮循环都要赋值
target[arrayItem || objItem] = data[p];
}
return result;
};