# Js实现扁平化数据结构和tree转换 --每天进步一点点

·  阅读 6801

## 写在前面

1. 扁平化的数组

``````let arr = [
{id: 1, name: '1', pid: 0},
{id: 2, name: '2', pid: 1},
{id: 3, name: '3', pid: 1},
{id: 4, name: '4', pid: 3},
{id: 5, name: '5', pid: 3},
]
复制代码``````
2. tree

``````let tree = [
{
"id": 1,
"name": "1",
"pid": 0,
"children": [
{
"id": 2,
"name": "2",
"pid": 1,
"children": []
},
{
"id": 3,
"name": "3",
"pid": 1,
"children": [
{
"id": 4,
"name": "4",
"pid": 3,
"children": []
}
]
}
]
}
]
复制代码``````

## `tree`扁平化

### 1. 递归实现

``````function treeToArray(tree) {
let res = []
for (const item of tree) {
const { children, ...i } = item
if (children && children.length) {
res = res.concat(treeToArray(children))
}
res.push(i)
}
return res
}

### 2. reduce实现

``````function treeToArray(tree) {
return tree.reduce((res, item) => {
const { children, ...i } = item
return res.concat(i, children && children.length ? treeToArray(children) : [])
}, [])
}

## 扁平化数组转`tree`

### 1. 递归实现

``````function arrayToTree(items) {
let res = []
let getChildren = (res, pid) => {
for (const i of items) {
if (i.pid === pid) {
const newItem = { ...i, children: [] }
res.push(newItem)
getChildren(newItem.children, newItem.id)
}
}
}
getChildren(res, 0)
return res
}

### 2. map对象实现

#### 先转`map`再找对应关系

Object.prototype.hasOwnProperty: 方法会返回一个布尔值，指示对象自身属性中是否具有指定的属性，会忽略掉那些从原型链上继承到的属性。

``````function arrayToTree(items) {
let res = [] // 存放结果集
let map = {}

// 先转成map存储
for (const i of items) {
map[i.id] = { ...i, children: [] }
}

for (const i of items) {
const newItem = map[i.id]
if (i.pid === 0) {
res.push(newItem)
} else {
if (Object.prototype.hasOwnProperty.call(map, i.pid)) {
map[i.pid].children.push(newItem)
}
}
}
return res
}

#### 边做`map`存储，边找对应关系

``````function arrayToTree(items) {
let res = [] // 存放结果集
let map = {}
// 判断对象是否有某个属性
let getHasOwnProperty = (obj, property) => Object.prototype.hasOwnProperty.call(obj, property)

// 边做map存储，边找对应关系
for (const i of items) {
map[i.id] = {
...i,
children: getHasOwnProperty(map, i.id) ? map[i.id].children : []
}
const newItem = map[i.id]
if (i.pid === 0) {
res.push(newItem)
} else {
if (!getHasOwnProperty(map, i.pid)) {
map[i.pid] = {
children: []
}
}
map[i.pid].children.push(newItem)
}
}
return res
}