簡體   English   中英

JavaScript:將線性 JSON 數組轉換為深度未知的樹結構

[英]JavaScript: Convert linear JSON array into tree structure with unknown depth

我有一個這樣的 JavaScript 數組:

[{ 
   name:'a'
   level:1
 },{ 
   name:'b'
   level:2
 },{
   name:'c'
   level:3
 },{ 
   name:'d'
   level:2
 },{ 
   name:'e'
   level:1
 },{ 
   name:'f'
   level:2
 },{ 
   name:'g'
   level:2
 },{
   name: 'f',
   level: 1
 }
]

我需要將其轉換為基於對象level屬性的樹結構

[{
    name: 'a'
    level: 1
    children: [{
        name: 'b'
        level: 2,
        children: [{
            name: 'c',
            level: 3
        }]
    }, {
        name: 'd'
        level: 2
    }]
}, {
    name: 'e'
    level: 1,
    children: [{
        name: 'f'
        level: 2
    }, {
        name: 'g'
        level: 2
    }]
}, {
    name: 'f',
    level: 1
}]

我嘗試過編寫許多函數並嘗試了許多方法但都失敗了。 我意識到的一件事是,這只能通過編寫遞歸函數來實現。 請幫忙。

注意:級別深度不限於3,未知

這是一個快速的方法:

var res = convert(a);

console.log(res);

function convert(arr) {
    return treeify(splitToSegments(arr));
}

function splitToSegments(arr) {
    var ret = [];
    var accum, segment;

    arr.forEach(function(o) {
        if (o.level === 1) {
            accum = true;

            if (segment && segment.length) {
                ret.push(segment);
            }

            segment = [o];
        } else if (accum) {
            segment.push(o);
        }
    });

    if (segment && segment.length) {
        ret.push(segment);
    }

    return ret;
}

function treeify(arr) {
    return arr.map(function(o) {
        return o.reduce(function(a, b) {
            var lastChild;

            a.children = a.children || [];

            if (a.level + 1 === b.level) {
                a.children.push(b);
            } else {
                lastChild = a.children[a.children.length - 1];

                lastChild.children = lastChild.children || [];

                lastChild.children.push(b);
            }

            return a;
        });
    });
}

請注意, treeify可能需要一些額外的邏輯來處理兄弟姐妹,但這應該是一個不錯的起點。

我遇到了完全相同的問題,這是我的解決方案:

function constructTree (flatList) {
const tree = [];

const clonedList = cloneDeep(flatList);
let root = {};
function append (child, parent) {
    if (Array.isArray(parent.children)) {
        parent.children.push(child);
    } else {
        parent.children = [child];
    }
    return parent;
}

function appendParentAdjacentNode (level, node, nodes) {
    if (level === 0) {
        nodes.push(node);
        return node;
    }
    while (level > 0) {
        return appendParentAdjacentNode(level - 1, node, nodes[0].children);
    }
    return node;
}

let parent;
for (let i = 0; i < clonedList.length; i++) {
    const currentNode = clonedList[i];
    const previousNode = clonedList[i - 1];
    const isRoot = currentNode.level === 0;
    if (isRoot) {
        root = currentNode;
        tree.push(root);
        continue;
    }
    const isChild = currentNode.level > previousNode.level;
    const isSibling = currentNode.level === previousNode.level;
    const isParentAdjacent = currentNode.level < previousNode.level;
    if (isChild) {
        parent = previousNode;
    }
    if (isChild || isSibling) {
        append(currentNode, parent);
    }
    if (isParentAdjacent) {
        appendParentAdjacentNode(currentNode.level - 1, currentNode, root.children);
    }
}
return tree;
}

簡要說明:

  • 為了保持函數的純潔性,我在操作之前克隆了輸入 (flatList)。
  • 該解決方案基於假設,如果當前節點的級別更高,則前一個節點是當前節點的父節點。
  • “父相鄰節點”只是層次結構中較高的節點,但不是當前節點的直接父節點(我認為它是叔叔/阿姨)。 如果你有更好的名字,請分享你的建議。
  • 在我的場景中,根節點的級別為 0。然而,在提問者的場景中,根節點的級別為 1。
  • 我正在使用遞歸來附加父相鄰節點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM