得到的层次结构的层次层次、结构

2023-09-11 04:24:53 作者:我好想你却不露痕迹

我有对象的数组,其中每个对象都有一个 ID 的ParentId 属性(这样他们就可以被安排在树)。他们在没有特定的顺序。

I have an array of objects, Where each object has an id and a ParentId property (so they can be arranged in trees). They are in no particular order.

请注意, ID parentId的的不会是整数,他们将字符串(只是想有样本code清洁..)

Please note that the id's and parentId's will not be integers, they will be strings (just wanted to have the sample code cleaner..)

只有一个根:可以说,它的 ID :1 这些数据看起来像这样:

There is only one root: lets say its id:1 The data looks like so:

 data = [
   {
        id:"id-2",
        parentId:"id-3"
    },
    {
        id:"id-4",
        parentId:"2"
    },
    {
        id:"id-3",
        parentId:"id-4"
    },
    {
        id:"id-5",
        parentId:"id-4"
    },
    {
        id:"id-6",
        parentId:"id-1"
    },
    {
        id:"id-7",
        parentId:"id-1"
    }
    // and so on...
]

我要寻找一个有效的方法,让每个对象水平属性,该属性应指定嵌套层次是...

I am looking for a efficient way to give each object a level property which should specify the nested level it is...

他们应该再是这样的:

data = [
    {
        id:"id-2",
        parentId:"id-1",
        level:2
    },
    {
        id:"id-3",
        parentId:"id-4",
        level:5

    },
    {
        id:"id-4",
        parentId:"id-2",
        level:3

    },
    {
        id:"id-5",
        parentId:"id-4",
        level:5
    },
    {
        id:"id-6",
        parentId:"id-1",
        level:2

    },
    {
        id:"id-7",
        parentId:"id-3",
        level:4
    }
    // and so on...
]

简而言之:

我要那个水平要通过循环直通阵列,并找出层级动态添加..

In short:

I want that level to be added dynamically via looping thru the array and figuring out the hierarchy..

此外,(如果更多钞票),他们然后应该按照有顺序排序,比如像所有对象级别:3 的从同一祖先应该是下一个对方,不应该有相同的父母兄弟姐妹彼此相邻而不是彼此相邻的3级两个表兄弟。

Additionally, (if posible) they should then be sorted according to there order, like for instance all objects level:3's from the same parent should be next to each other, not that there should be siblings of the same parent next to each other rather then two cousins of level 3 next to each other.

推荐答案

的低于code一个工作的例子是上的的jsfiddle 。

A working example of the below code is on jsFiddle.

指数由ID树和遍历向上,从每个节点,并计数,直到你打根。通过索引第一,我们接近O(n)的时间复杂度(根据树的密度)。 *的更新,以满足排序要求,并允许排除根节点的

Index the tree by id and traverse it upwards, from each node, and count until you hit the root. By indexing first, we approach O(n) time complexity (depending on tree density). *Updated to satisfy the sorting requirement, and allow exclusion of root node:

function levelAndSort(data, startingLevel) {
    // indexes
    var indexed = {};        // the original values
    var nodeIndex = {};      // tree nodes
    var i;
    for (i = 0; i < data.length; i++) {
        var id = data[i].id;
        var node = {
            id: id,
            level: startingLevel,
            children: [],
            sorted: false
        };
        indexed[id] = data[i];
        nodeIndex[id] = node;
    }

    // populate tree
    for (i = 0; i < data.length; i++) {
        var node = nodeIndex[data[i].id];
        var pNode = node;
        var j;
        var nextId = indexed[pNode.id].parentId;
        for (j = 0; nextId in nodeIndex; j++) {
            pNode = nodeIndex[nextId];
            if (j == 0) {
                pNode.children.push(node.id);
            }
            node.level++;
            nextId = indexed[pNode.id].parentId;
        }
    }

    // extract nodes and sort-by-level
    var nodes = [];
    for (var key in nodeIndex) {
        nodes.push(nodeIndex[key]);
    }
    nodes.sort(function(a, b) {
        return a.level - b.level;
    });

    // refine the sort: group-by-siblings
    var retval = [];
    for (i = 0; i < nodes.length; i++) {
        var node = nodes[i];
        var parentId = indexed[node.id].parentId;
        if (parentId in indexed) {
            var pNode = nodeIndex[parentId];
            var j;
            for (j = 0; j < pNode.children.length; j++) {
                var child = nodeIndex[pNode.children[j]];
                if (!child.sorted) {
                    indexed[child.id].level = child.level;
                    retval.push(indexed[child.id]);
                    child.sorted = true;
                }
            }
        }
        else if (!node.sorted) {
            indexed[node.id].level = node.level;
            retval.push(indexed[node.id]);
            node.sorted = true;
        }
    }
    return retval;
}

例:

// level 0 (root) excluded
var startingLevel = 1;
var someData = [
    {id : "id-1", parentId : "id-0"},
    {id : "id-2", parentId : "id-0"},
    {id : "id-3", parentId : "id-2"},
    {id : "id-4", parentId : "id-3"},
    {id : "id-5", parentId : "id-4"},
    {id : "id-6", parentId : "id-4"},
    {id : "id-7", parentId : "id-0"},
    {id : "id-8", parentId : "id-1"},
    {id : "id-9", parentId : "id-7"},
    {id : "id-10", parentId : "id-1"},
    {id : "id-11", parentId : "id-1"},
    {id : "id-12", parentId : "id-1"}
];
var outputArray = levelAndSort(someData, startingLevel);

输出:

Output:

如果你改变输入顺序,排序出来有点不同,但它仍然是正确的(即在一级阶,由同级分组)。

If you change the input order, the sort comes out a little different, but it's still correct (i.e., in level-order, grouped by sibling).