js implements flat data structure and tree conversion

Preface

We should all have encountered this need in projects: flattening the tree, or converting the flattened data into a tree structure, which usually occurs in projects such as system authorization. The next step is to convert the data processing into The format required by the backend

Flatten data

  • flattened array
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 },
]
  • 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 flattening

Recursive implementation

  • Traverse the tree and add each item to the result set. If there are children and the length is not 0, recursively traverse
  • Here you need to use destructuring assignment to remove the children attribute of each node.
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
}

reduce implementation

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

Flatten array to tree

Recursive implementation

  • The most commonly used method is recursive implementation, and the idea is relatively simple. Implement a method that passes in the tree parent node and parent id, loops through the array query, finds the corresponding child node, pushes it to the parent node, and then recursively finds the child node. child nodes of
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
}

map object implementation

  • 1. First transfer the map and then find the corresponding relationship.
    • Idea: First convert the data into a Map for storage, and then use the reference of the object to directly find the corresponding data from the Map for storage while traversing
    • Object.prototype.hasOwnProperty: The method will return a Boolean value indicating whether the object's own properties have the specified properties, and will ignore those properties inherited from the prototype chain.
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
}
  • 2. While doing map storage, find the corresponding relationship.
    • Idea: Loop the id of the item as the key and store it in the map. If there is already a key-value pair, there is no need to store it. At the same time, find if the pid of the item is not in the key of the map. It directly corresponds to the parent-child relationship. If it is not Just generate a key-value pair in the map, the key is the pid, and then correspond to the parent-child relationship
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
}

Guess you like

Origin blog.csdn.net/yuan0209/article/details/128038184