平级转树结构

var data = {
  "organization": [
    {
      "id": "1",
      "pid": "0",
      "organization": "/A"
    },
    {
      "id": "2",
      "pid": "0",
      "organization": "/AA"
    },
    {
      "id": "11",
      "pid": "1",
      "organization": "/A/B"
    },
    {
      "id": "22",
      "pid": "2",
      "organization": "/AA/BB"
    },
    {
      "id": "44",
      "pid": "2",
      "organization": "/AA/CC"
    }
  ],
  "user": [
    {
      "id": "xxxx",
      "pid": "2",
      "email": "yu@test.com",
      "organization": "/A",
      "display_name": "玉"
    },
    {
      "id": "yyy",
      "pid": "2",
      "email": "yy@test.com",
      "organization": "/A/B",
      "display_name": "哈"
    },    
    {
      "id": "zzzz",
      "pid": "22",
      "email": "nn@test.com",
      "organization": "/AA/BB",
      "display_name": "欧式"
    },
    {
      "id": "hhhh",
      "pid": "44",
      "email": "yfef@test.com",
      "organization": "/AA/CC",
      "display_name": "红"
    },    
    {
      "id": "effef",
      "pid": "44",
      "email": "yfesf@test.com",
      "organization": "/AA/CC",
      "display_name": "xe"
    }
  ]
}

如果是organization数组中的话title字段显示组织,如果是user数组中的话title字段显示email

如何把以上结构转成树结构?

阅读 3.4k
4 个回答
let flatArr = [
    { id: 0, pId: null, },
    { id: 1, pId: 2, },
    { id: 2, pId: 0, },
]

const flatToNest = (arr, id = null, key = 'pId') => arr
    .filter(item => item[key] === id)
    .map(item => ({ ...item, children: flatToNest(arr, item.id) }))
    
// output
let result = flatToNest(flatArr)

    [
        {
            id: 0,
            pId: null,
            children: [
                {
                    id: 2,
                    pId: 0,
                    children: [
                        {
                            id: 1,
                            pId: 2,
                            children: [],
                        }
                    ],
                }
            ],
        }
    ]

看你这个其实只有组织是树结构,不过树结构中的一些叶子节点是人员。
和一般的平级转树形也差不多,我写一下思路吧:
1.声明一个空对象info={},遍历organization数组,给每个org加上children字段,并设置title字段,将组织id和organization映射放到info中,做快速索引。
2.再次遍历orgnization,对于每一项org,通过pid从info中找到其父级parent,将org追加到paren.children
3.对于user列表,同样遍历,类似步骤2


看到楼下写了O(n^2)以上时间复杂度的代码,还是贴一下O(n)的代码吧:

function toTree (data) {
  let { organization: orgList, user: userList } = data
  let result = []
  let orgInfo = {} // 快速映射
  orgList.forEach(org => {
    orgInfo[org.id] = org
    org.children = []
    org.title = org.organization
  })
  orgList.forEach(org => orgInfo[org.pid] ? orgInfo[org.pid].children.push(org) : result.push(org))
  
  userList.forEach(user => {
    user.title = user.email
    orgInfo[user.pid] && orgInfo[user.pid].children.push(user)
  })
  return result
}

调用:

let result = toTree(data)
console.log(JSON.stringify(result))

输出:

[
    {
        "id":"1",
        "pid":"0",
        "organization":"/A",
        "children":[
            {
                "id":"11",
                "pid":"1",
                "organization":"/A/B",
                "children":[

                ],
                "title":"/A/B"
            }
        ],
        "title":"/A"
    },
    {
        "id":"2",
        "pid":"0",
        "organization":"/AA",
        "children":[
            {
                "id":"22",
                "pid":"2",
                "organization":"/AA/BB",
                "children":[
                    {
                        "id":"zzzz",
                        "pid":"22",
                        "email":"nn@test.com",
                        "organization":"/AA/BB",
                        "display_name":"欧式",
                        "title":"nn@test.com"
                    }
                ],
                "title":"/AA/BB"
            },
            {
                "id":"44",
                "pid":"2",
                "organization":"/AA/CC",
                "children":[
                    {
                        "id":"hhhh",
                        "pid":"44",
                        "email":"yfef@test.com",
                        "organization":"/AA/CC",
                        "display_name":"红",
                        "title":"yfef@test.com"
                    },
                    {
                        "id":"effef",
                        "pid":"44",
                        "email":"yfesf@test.com",
                        "organization":"/AA/CC",
                        "display_name":"xe",
                        "title":"yfesf@test.com"
                    }
                ],
                "title":"/AA/CC"
            },
            {
                "id":"xxxx",
                "pid":"2",
                "email":"yu@test.com",
                "organization":"/A",
                "display_name":"玉",
                "title":"yu@test.com"
            },
            {
                "id":"yyy",
                "pid":"2",
                "email":"yy@test.com",
                "organization":"/A/B",
                "display_name":"哈",
                "title":"yy@test.com"
            }
        ],
        "title":"/AA"
    }
]

如有问题请追问,如有帮助请给个赞~,~

const nodes = [{ 
  // 当前节点 id
  id: '1', 
  // 父节点 id
  pid: '0',  
  ...
}, ...]


// 为每个节点寻找子节点
function attachChildrenForNode(parentNode) {
  const children = nodes.filter(node => node.pid === parentNode.id)
                      .map(child => attachChildrenForNode(child))
  children.forEach(child => {
    child.parent = parentNode
  })
  parentNode.children = children

  return parentNode
}

// 父节点 id 为 '0',即顶级节点
const roots = nodes.filter(node => node.pid === '0').map(node => attachChildrenForNode(node))

数组构造为树的方法如上,title 什么的往里加代码就行了。

let organization = data.organization
let user = data.user

function tree(organization, user) {
  // 筛选出顶层组织
  let topOrg = organization.filter(org => org.pid == 0)
  findChildren(topOrg, organization, user)
  return topOrg
}

function findChildren(topOrg, organization, user) {
  topOrg.forEach(ele => {
    // 找出本组织下的直系组织
    ele.children = organization.filter(org => org.pid == ele.id)
    // 将本组织的人员加进来 
    ele.user = user.filter(u => u.pid == ele.id)
    // 如果直系存在 递归直系的直系
    if (ele.children.length) findChildren(ele.children, organization, user)
  })
}

console.dir(tree(organization, user))
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题