我有对象的数组,其中每个对象都有一个 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...
]
我要那个水平
要通过循环直通阵列,并找出层级动态添加..
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);
如果你改变输入顺序,排序出来有点不同,但它仍然是正确的(即在一级阶,由同级分组)。
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).