背景
假设我们有一堆评论的数据需要存储,通常来说数据库中是上面的扁平形式,而我们显示出来应该是树形结构。
于是就有了这里的内容,扁平结构和树形结构相互转换。
扁平转树状
如下,内容都在注释里:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| const flatComments = [ { id: 1, content: 'A', parent: -1 }, { id: 2, content: 'B', parent: -1 }, { id: 3, content: 'C', parent: 1 }, { id: 4, content: 'D', parent: 3 }, { id: 5, content: 'E', parent: 2 }, ]
function toTree(arr) { const root = []
arr = arr.map(item => ({ ...item }))
const map = arr.reduce((pre, cur) => { pre[cur.id] = cur return pre }, {})
map[-1] = { children: root }
arr.forEach(item => { const children = map[item.parent].children ||= [] children.push(item) })
return root }
console.log(toTree(flatComments))
|
读者可以打开控制台试一试,看看是否为预期效果。
树状转扁平
其实这个要简单得多,直接递归调用即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| const treeComments = [ { id: 1, content: 'A', children: [ { id: 3, content: 'C', children: [{ id: 4, content: 'D', children: [] }] } ] }, { id: 2, content: 'B', children: [{ id: 5, content: 'E', children: [] }] } ]
function toFlat(tree) { const result = []
const convert = ({ id, content, children }, parent) => { result.push({ id, content, parent }) children.forEach(child => { convert(child, id) }) }
tree.forEach(root => { convert(root, -1) }) return result }
console.log(toFlat(treeComments))
|
读者可以打开控制台试一试,看看效果如何。
后记
如果要追求效率,不必像本文中一样拷贝原始数据,直接在原对象上修改即可。
不过考虑到诸多bug都是由于对象引用混乱造成的,所以在写代码的时候需要注意这一点。