使用 lodash.js 将平面数组转换为树形数组
Flat array to tree array using lodash.js
我正在尝试将平面数组转换为树形数组,因为我将使用 jsTree 中的数据。我还需要将 "Name" 之类的键名转换为 "text"。
我想使用 lodash.js 但我真的是 lodash 的新手。我搜索了解决方案,但找不到适合我的情况。
那么你能帮忙吗?我的平面阵列数据如下:
[
{
Id:1,
Name: 'name1',
Parent: 0
},
{
Id:2,
Name: 'name2',
Parent: 1
},
{
Id:3,
Name: 'name3',
Parent: 2
},
{
Id:4,
Name: 'name4',
Parent: 1
},
{
Id:5,
Name: 'name5',
Parent: 1
},
{
Id:6,
Name: 'name6',
Parent: 5
}
]
我想要像这样的树数据:
{
"id": 1,
"text" : "name1",
"children" : [
{
"id": 2,
"text" : "name2",
"children" : [{
"id": 3,
"text": "name3"
}]
},
{
"id": 4,
"text" : "name4"
},
{
"id": 5,
"text" : "name5",
"children" : [{
"id": 6,
"text": "name6"
}]
}
]
}
提前致谢
这是针对未排序数据的纯 Javascript 提议。
var data = [{ Id: 1, Name: 'name1', Parent: 0 }, { Id: 2, Name: 'name2', Parent: 1 }, { Id: 3, Name: 'name3', Parent: 2 }, { Id: 4, Name: 'name4', Parent: 1 }, { Id: 5, Name: 'name5', Parent: 1 }, { Id: 6, Name: 'name6', Parent: 5 }],
tree = function (data, root) {
var r;
data.forEach(function (a) {
this[a.Id] = { id: a.Id, text: a.Name, children: this[a.Id] && this[a.Id].children };
if (a.Parent === root) {
r = this[a.Id];
} else {
this[a.Parent] = this[a.Parent] || {};
this[a.Parent].children = this[a.Parent].children || [];
this[a.Parent].children.push(this[a.Id]);
}
}, Object.create(null));
return r;
}(data, 0);
document.write('<pre>' + JSON.stringify(tree, 0, 4) + '</pre>');
如果您不确定child是否不能出现在parent之前,那么您可以使用此代码:
var t = [{ Id: 1, Name: 'name1', Parent: 0 }, { Id: 2, Name: 'name2', Parent: 1 }, { Id: 3, Name: 'name3', Parent: 2 }, { Id: 4, Name: 'name4', Parent: 1 }, { Id: 5, Name: 'name5', Parent: 1 }, { Id: 6, Name: 'name6', Parent: 5 }];
var elements = [];
t.forEach(function(element) {
elements[element.Id] = {
id: element.Id,
text: element.Name,
parent: element.Parent,
children: []
}
});
elements.forEach(function(element) {
elements[element.parent] && elements[element.parent].children.push(element);
delete element.parent;
})
document.write(['<pre>', JSON.stringify(elements[1], 0, 3), '</pre>'].join(''));
类似于
return _(data).map(function(val) { val.children = []; })
.map(function(val, key) {
data[val.parent].children.push(val);
});
滥用数组索引。您可能需要先在源数据中构建一个从Id
到index
的辅助映射。
这只是 Array.map
的普通用法,因此此解决方案不需要 lodash。
下面的函数根据对象列表构建树。
对任何格式都不严格。
function buildTree(flatList, idFieldName, parentKeyFieldName, fieldNameForChildren) {
var rootElements = [];
var lookup = {};
flatList.forEach(function (flatItem) {
var itemId = flatItem[idFieldName];
lookup[itemId] = flatItem;
flatItem[fieldNameForChildren] = [];
});
flatList.forEach(function (flatItem) {
var parentKey = flatItem[parentKeyFieldName];
if (parentKey != null) {
var parentObject = lookup[flatItem[parentKeyFieldName]];
if(parentObject){
parentObject[fieldNameForChildren].push(flatItem);
}else{
rootElements.push(flatItem);
}
} else {
rootElements.push(flatItem);
}
});
return rootElements;
}
Here is a fiddle 使用您的示例作为输入。
原始出处comes from this answer.
我正在尝试将平面数组转换为树形数组,因为我将使用 jsTree 中的数据。我还需要将 "Name" 之类的键名转换为 "text"。
我想使用 lodash.js 但我真的是 lodash 的新手。我搜索了解决方案,但找不到适合我的情况。
那么你能帮忙吗?我的平面阵列数据如下:
[
{
Id:1,
Name: 'name1',
Parent: 0
},
{
Id:2,
Name: 'name2',
Parent: 1
},
{
Id:3,
Name: 'name3',
Parent: 2
},
{
Id:4,
Name: 'name4',
Parent: 1
},
{
Id:5,
Name: 'name5',
Parent: 1
},
{
Id:6,
Name: 'name6',
Parent: 5
}
]
我想要像这样的树数据:
{
"id": 1,
"text" : "name1",
"children" : [
{
"id": 2,
"text" : "name2",
"children" : [{
"id": 3,
"text": "name3"
}]
},
{
"id": 4,
"text" : "name4"
},
{
"id": 5,
"text" : "name5",
"children" : [{
"id": 6,
"text": "name6"
}]
}
]
}
提前致谢
这是针对未排序数据的纯 Javascript 提议。
var data = [{ Id: 1, Name: 'name1', Parent: 0 }, { Id: 2, Name: 'name2', Parent: 1 }, { Id: 3, Name: 'name3', Parent: 2 }, { Id: 4, Name: 'name4', Parent: 1 }, { Id: 5, Name: 'name5', Parent: 1 }, { Id: 6, Name: 'name6', Parent: 5 }],
tree = function (data, root) {
var r;
data.forEach(function (a) {
this[a.Id] = { id: a.Id, text: a.Name, children: this[a.Id] && this[a.Id].children };
if (a.Parent === root) {
r = this[a.Id];
} else {
this[a.Parent] = this[a.Parent] || {};
this[a.Parent].children = this[a.Parent].children || [];
this[a.Parent].children.push(this[a.Id]);
}
}, Object.create(null));
return r;
}(data, 0);
document.write('<pre>' + JSON.stringify(tree, 0, 4) + '</pre>');
如果您不确定child是否不能出现在parent之前,那么您可以使用此代码:
var t = [{ Id: 1, Name: 'name1', Parent: 0 }, { Id: 2, Name: 'name2', Parent: 1 }, { Id: 3, Name: 'name3', Parent: 2 }, { Id: 4, Name: 'name4', Parent: 1 }, { Id: 5, Name: 'name5', Parent: 1 }, { Id: 6, Name: 'name6', Parent: 5 }];
var elements = [];
t.forEach(function(element) {
elements[element.Id] = {
id: element.Id,
text: element.Name,
parent: element.Parent,
children: []
}
});
elements.forEach(function(element) {
elements[element.parent] && elements[element.parent].children.push(element);
delete element.parent;
})
document.write(['<pre>', JSON.stringify(elements[1], 0, 3), '</pre>'].join(''));
类似于
return _(data).map(function(val) { val.children = []; })
.map(function(val, key) {
data[val.parent].children.push(val);
});
滥用数组索引。您可能需要先在源数据中构建一个从Id
到index
的辅助映射。
这只是 Array.map
的普通用法,因此此解决方案不需要 lodash。
下面的函数根据对象列表构建树。 对任何格式都不严格。
function buildTree(flatList, idFieldName, parentKeyFieldName, fieldNameForChildren) {
var rootElements = [];
var lookup = {};
flatList.forEach(function (flatItem) {
var itemId = flatItem[idFieldName];
lookup[itemId] = flatItem;
flatItem[fieldNameForChildren] = [];
});
flatList.forEach(function (flatItem) {
var parentKey = flatItem[parentKeyFieldName];
if (parentKey != null) {
var parentObject = lookup[flatItem[parentKeyFieldName]];
if(parentObject){
parentObject[fieldNameForChildren].push(flatItem);
}else{
rootElements.push(flatItem);
}
} else {
rootElements.push(flatItem);
}
});
return rootElements;
}
Here is a fiddle 使用您的示例作为输入。
原始出处comes from this answer.