我有一些数据
var currentData = [
{'ticket':'CAP', 'child':'CT-1'},
{'ticket':'CAP', 'child':'CT-2'},
{'ticket':'CT-1', 'child':'CT-1-A'},
{'ticket':'CT-1', 'child':'CT-1-B'}
];数据是扁平的,我需要将其转换为如下内容:
{
'ticket': 'CAP',
children : [{
'ticket' : 'CT-1',
'children' : [{
'ticket' : 'CT-1-A',
'children' : []
}, {
'ticket' : 'CT-1-B',
'children' : []
}],
[{
'ticket' : 'CT-2',
'children' : []
}]
}]
}(我认为以上是正确的)?
我完全不知道该怎么做。我要展示我的努力,但是,我不确定我的方法是否正确。
var currentData = [{'ticket':'cap', 'child':'CT-1'},{'ticket':'cap', 'child':'CT-2'}, {'ticket':'CT-1', 'child':'CT-1-A'},{'ticket':'CT-1', 'child':'CT-1-B'}];
var newList = [];
function convert(list){
if (newList.length <= 0){
var child = [];
var emptyChild = [];
child.push({'ticket': list[0].child, 'child': emptyChild });
newList.push({'ticket': list[0].ticket, 'children' : child});
list.splice(0,1);
} // the if statement above works fine
for(var i = 0; i < list.length; i++) {
var ticket = list[i].ticket;
for(var j = 0; j < newList.length; j++) {
if (newList[j].ticket == ticket){
var child;
var emptyChild = [];
child = {'ticket': list[i].child, 'child': emptyChild };
newList[j].children.push(child);
list.splice(i,1);
break;
} // the if above works
else{
var child2 = getFromChildren(ticket, newList, list[i]); // child2 is Always null, even if getFromChildren returns an object
newList[j].children.push(child2);
list.splice(i,1);
break;
}
}
}
if (list.length > 0){
convert(list);
}
}
function getFromChildren(ticket, list, itemToAdd){
if (list == null || list[0].children == null)
return;
for(var i = 0; i < list.length; i++) {
if (list[i] == null)
return;
if (list[i].ticket == ticket){
list[i].child.push(itemToAdd.child); // ** can't do this, javascript passes by value, not by reference :(
} else{
getFromChildren(ticket, list[i].children, itemToAdd);
}
}
}
convert(currentData);
我想我搞砸了。我在评论中解释说,由于JavaScript不通过引用传递,所以它不起作用,但是在further reading上,我认为这是不正确的,因为我是通过引用传递对象的。
编辑
用currentData显示的数据也不一定总是从根目录开始。
发布于 2017-09-15 14:27:36
function convert(arr) {
var children = {}; // this object will hold a reference to all children arrays
var res = arr.reduce(function(res, o) { // for each object o in the array arr
if(!res[o.ticket]) { // if there is no object for the element o.ticket
res[o.ticket] = {ticket: o.ticket, children: []}; // then creates an object for it
children[o.ticket] = res[o.ticket].children; // and store a reference to its children array
}
if(!res[o.child]) { // if there is no object for the element o.child
res[o.child] = {ticket: o.child, children: []}; // then creates an object for it
children[o.child] = res[o.child].children; // and store a reference to its children array
}
return res;
}, {});
arr.forEach(function(o) { // now for each object o in the array arr
children[o.ticket].push(res[o.child]); // add the object of o.child (from res) to its children array
delete res[o.child]; // and remove the child object from the object res
});
return res;
}
var currentData = [
{'ticket':'CAP', 'child':'CT-1'},
{'ticket':'CAP', 'child':'CT-2'},
{'ticket':'CT-1', 'child':'CT-1-A'},
{'ticket':'CT-1', 'child':'CT-1-B'}
];
console.log(convert(currentData));
解释:
reduce部分为每个元素(子元素或非子元素)创建表单的对象:{ ticket: "...", children: [] }。因此,在reduce之后,对象res将是:
res = {
'CAP': { ticket: 'CAP', children: [] },
'CT-1': { ticket: 'CT-1', children: [] },
'CT-2': { ticket: 'CT-2', children: [] },
'CT-1-A': { ticket: 'CT-1-A', children: [] },
'CT-1-B': { ticket: 'CT-1-B', children: [] },
}现在出现了forEach位,它再次遍历数组,现在对于每个对象,它从上面的res中获取.child对象,将其推入.ticket对象的children (对它的引用存储在children对象中),然后从对象res中删除.child对象。
发布于 2017-09-15 14:32:09
下面使用reduce将数据分组到Map中,然后像上面所示的那样将数据转换为一个对象。您需要一个现代浏览器才能在代码段下面运行,或者使用像babeljs这样的转换程序将其转换为es5语法。
let currentData = [
{'ticket':'CAP', 'child':'CT-1'},
{'ticket':'CAP', 'child':'CT-2'},
{'ticket':'CT-1', 'child':'CT-1-A'},
{'ticket':'CT-1', 'child':'CT-1-B'}
];
let children = currentData.map(e => e.child);
currentData.sort((a,b) => children.indexOf(a.ticket));
let res = currentData.reduce((a,b) => {
if (! children.includes(b.ticket)) {
return a.set(b.ticket, (a.get(b.ticket) || [])
.concat({ticket: b.child,
children: currentData
.filter(el => el.ticket === b.child)
.map(el => ({ticket: el.child, children: []}))}))
}
return a;
}, new Map);
let r = {};
for (let [key,value] of res.entries()) {
r.ticket = key;
r.children = value;
}
console.log(r);
发布于 2017-09-15 14:55:10
解决方案使用递归,可以更改起始节点。
var currentData = [{'ticket': 'cap','child': 'CT-1'}, {'ticket': 'cap','child': 'CT-2'}, {'ticket': 'CT-1','child': 'CT-1-A'}, {'ticket': 'CT-1','child': 'CT-1-B'}];
function convert(data, start){
return {
ticket: start,
childs: data.filter(d => d.ticket == start)
.reduce((curr, next) => curr.concat([next.child]), [])
.map(c => convert(data, c))
}
}
let result = convert(currentData, 'cap');
console.log(result);.as-console-wrapper{top: 0; max-height: none!important;}
https://stackoverflow.com/questions/46241210
复制相似问题