fe-learning
fe-learning copied to clipboard
树形数据结构扁平化
编写两个函数,实现如下两个数据结构互相转换
const data = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
const output = {
'a.b.c.dd': 'abcdd',
'a.d.xx': 'adxx',
'a.e': 'ae'
}
// 辅助函数
const isObj = obj => Object.prototype.toString.call(obj) === '[object Object]'
// 扁平化树形结构
function flattenNTreeHelper (data, ans, prevKey = '') {
Object.keys(data).forEach(key => {
const currKey = prevKey ? prevKey + '.' + key : key
const currVal = data[key]
if (isObj(currVal)) {
flattenNTreeHelper(currVal, ans, currKey)
} else {
ans[currKey] = currVal
}
})
}
function flattenNTree (data) {
if (!isObj(data)) return data
const ans = {}
flattenNTreeHelper(data, ans, '')
return ans
}
// 扁平化结构转树形
function nTreeConstruct (data) {
if (!isObj(data)) return data
const ans = {}
Object.keys(data).forEach(key => {
// 按 . 分割key, 顺带支持一下形如 'z[0]'的格式
const keys = key.replace(/\[(\d+)\]/g, '.$1').split('.')
let curr = ans
for (let i = 0; i < keys.length - 1; i++) {
curr[keys[i]] = curr[keys[i]] || {}
curr = curr[keys[i]]
}
curr[keys[keys.length - 1]] = data[key]
})
return ans
}
再考虑以下数据:
const data = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
e: 'ae',
g: [1, { g1: 6 }, [1, 2]]
}
}
// 期望输出
const output = {
'a.b.c.dd': 'abcdd',
'a.e': 'ae',
'g[0]': 1,
'g[1].g1': 6,
'g[2][0]': 1,
'g[2][1]': 2
}
也就是生成key的时候要多考虑一个数组类型,实现如下:
function flattenNTreeHelper (data, ans, prevKey = '', isArr = false) {
Object.keys(data).forEach(key => {
const currKey = prevKey ? (prevKey + (isArr ? ('[' + key + ']') : ('.' + key))) : key
const currVal = data[key]
const dataIsArr = Array.isArray(currVal)
if (isObj(currVal) || dataIsArr) {
flattenNTreeHelper(currVal, ans, currKey, dataIsArr)
} else {
ans[currKey] = currVal
}
})
}