js数组转树

267 阅读2分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。

  树结构在开发中是比较常见的数据结构。那么在拿到如下包含父子关系的数组数据情况下怎么才能转变为树结构的数据呢?

// 包含父子关系的数组数据
var data = [
    {id: 1, sid: '', mc: '测试1'}
    ,{id: 2, sid: '', mc: '测试2'}
    ,{id: 11, sid: '1', mc: '测试11'}
    ,{id: 12, sid: '1', mc: '测试12'}
    ,{id: 21, sid: '2', mc: '测试21'}
    ,{id: 22, sid: '2', mc: '测试22'}
    ,{id: 121, sid: '12', mc: '测试121'}
]
// 树结构数据
d = [
    {id: 1, sid: '', mc: '测试1', child: [
        {id: 11, sid: '1', mc: '测试11'}
        ,{id: 12, sid: '1', mc: '测试12', child: [
            {id: 121, sid: 12, mc: '测试121'}
        ]}
    ]}
    ,{id: 2, sid: '', mc: '测试2', child: [
        {id: 21, sid: '2', mc: '测试21'}
        ,{id: 22, sid: '2', mc: '测试22'}
    ]}
]

方案一

  分析上面的数组数据我们能够发现数据和数据之间可以通过id、sid相互关联。同时数据可以分为两类:一类数据不包含子节点的数据;一类包含字节点的数据。我们要做的就是将每一条数据分门别类的归纳到其父数据中。然后筛选出不包含父节点的数据。

// 数据归类到其指定的数据中
var len = data.length, result = []
for (var i = 0; i < len; i++) {
    var it = data[i], judge = true
    for (var j = 0; j < len; j++) {
        var it1 = data[j]
        if (it.id == it1.sid) {
            it.child = it.child ? it.child : []
            it.child.push(it1)
            judge = false
        }
    }
}
// 获取不包含父节点数据的
for (var i = 0; i < len; i++) {
    var it = data[i], judge = true
    for (var j = 0; j < len; j++) {
        var it1 = data[j]
        if (it.sid == it1.id) {
            judge = false
            break
        }
    }
    judge && result.push(it)
}

方案二

  分析上面的数组数据我们能够发现数据和数据之间可以通过id、sid相互关联。同时数据可以分为两类:一类数据不包含父节点的数据;一类包含父节点的数据。我们可以先将两类数据筛选出来,然后通过递归将第二类数据归档第一类中。

var len = data.length, result = [], c = []
// 获取不包含父节点数据的
for (var i = 0; i < len; i++) {
    var it = data[i], judge = true
    for (var j = 0; j < len; j++) {
        var it1 = data[j]
        if (it.sid == it1.id) {
            judge = false
            break
        }
    }
    if (judge) {
        result.push(it)
    } else {
        c.push(it)
    }
}
// 通过父级节点匹配获取子节点
function getChild(data, sid) {
    var length = data.length, result = []
    for (var i = 0; i < len; i++) {
        var it = data[i]
        if (it && it.sid == sid) {
            result.push(it)
            // 递归调用获取子节点
            it.child = getChild(c, it.id)
        }
    }
    return result
}
// 获取不包含父节点数据的子节点
length = result.length
for (var i = 0; i < len; i++) {
    var it = result[i]
    it && (it.child = getChild(c, it.id))
}