我有一些存储在嵌套JSON中的名称数组,如下所示:
{
"groupZ": {
"names": [
"Steve",
"Henry"
]
},
"groupY": {
"groupA": {
"names": [
"Laura"
]
},
"groupB": {
"names": [
"Alice",
"Bob",
"Neil"
]
}
},
"groupX": {
"groupC": {
"groupD": {
"names": [
"Steph"
]
}
},
"groupE": {
"names": [
"Aaron",
"Dave"
]
}
}
}
我试图弄清楚如何生成所有名称的列表,前面加上每个名称的完整组路径,所以它最终会像这样:
组名在每个级别都是唯一的,但除此之外可以被称为任何东西。我知道我需要递归调用一个函数,当它找到一个" name"数组,通过一个字符串来添加到每个递归的前置,但有真正的麻烦。到目前为止,这是我的代码:
var sPrepend = '';
function buildList(Groups, lastGroupName){
for(var thisGroupName in Groups) {
var thisGroup = Groups[thisGroupName];
if(!thisGroup.names){
sPrepend += (' - ' + thisGroupName);
buildList(thisGroup, thisGroupName);
}
if(thisGroup.names){
thisGroup.names.forEach(function(name){
console.log(sPrepend, ' - ', name);
//build the list item here.
});
}
}
}
buildList(oGroups, '');
由于我无法改变JSON结构,但我确信这是可能的,这让我很难过。谢谢任何可以提供帮助的人!
答案 0 :(得分:3)
这对我有用:
function buildList(group, accum, key) {
// default helper parameters
accum = accum || [];
key = key || '';
if (group.names) { // add each name
group.names.forEach(function(name) {
accum.push(key + name);
});
} else { // or recurse on each key
Object.getOwnPropertyNames(group).forEach(function(gname) {
buildList(group[gname], accum, key + gname + ' - ');
});
}
return accum;
}
var list = buildList(oGroups);
答案 1 :(得分:0)
是的,你很亲密。您只需要确保将连接的组名称(previous + current)传递给递归函数。
Alnitak的解决方案总体上比较整洁。
function buildList(Groups, lastGroupName){
for(var thisGroupName in Groups) {
var thisGroup = Groups[thisGroupName];
var currGroupName = lastGroupName + ' - ' + thisGroupName;
if(!thisGroup.names){
buildList(thisGroup, currGroupName);
}
if(thisGroup.names){
thisGroup.names.forEach(function(name){
console.log(currGroupName + ' - ' + name);
//build the list item here.
});
}
}
}
var oGroups = {
"groupZ": {
"names": [
"Steve",
"Henry"
]
},
"groupY": {
"groupA": {
"names": [
"Laura"
]
},
"groupB": {
"names": [
"Alice",
"Bob",
"Neil"
]
}
},
"groupX": {
"groupC": {
"groupD": {
"names": [
"Steph"
]
}
},
"groupE": {
"names": [
"Aaron",
"Dave"
]
}
}
};
buildList(oGroups, '');
我假设您最终还希望将此作为列表返回,这需要更多的努力。
function buildList(Groups, lastGroupName){
var ret = [];
for(var thisGroupName in Groups) {
var thisGroup = Groups[thisGroupName];
var currGroupName = lastGroupName + ' - ' + thisGroupName;
if(!thisGroup.names){
var childNames = buildList(thisGroup, currGroupName);
for(var i = 0; i < childNames.length; i++) {
ret.push(childNames[i]);
}
}
if(thisGroup.names){
thisGroup.names.forEach(function(name){
//console.log(currGroupName + ' - ' + name);
//build the list item here.
ret.push(currGroupName + ' - ' + name);
});
}
}
return ret;
}
var oGroups = {
"groupZ": {
"names": [
"Steve",
"Henry"
]
},
"groupY": {
"groupA": {
"names": [
"Laura"
]
},
"groupB": {
"names": [
"Alice",
"Bob",
"Neil"
]
}
},
"groupX": {
"groupC": {
"groupD": {
"names": [
"Steph"
]
}
},
"groupE": {
"names": [
"Aaron",
"Dave"
]
}
}
};
var x = buildList(oGroups, '');
for(var i = 0; i < x.length; i++) {
console.log(x[i]);
}
答案 2 :(得分:0)
您可以为路径选择一个数组并调用不带该参数的函数,因为它将被检查,如果不是truthy,则会分配一个数组。
在对象的键的循环中,检查键是否为names
,并且该数组与路径一起显示。
如果键不等于names
,则检查实际属性,如果它是可迭代对象,则使用带有实际键的扩展数组再次调用该函数。
function buildList(object, path) {
path = path || [];
Object.keys(object).forEach(function (k) {
if (k === 'names') {
object.names.forEach(function (name) {
console.log(path.concat(name).join(' - '));
});
return;
}
if (object[k] && typeof object[k] === 'object') {
buildList(object[k], path.concat(k));
}
});
}
var data = { groupZ: { names: ["Steve", "Henry"] }, groupY: { groupA: { names: ["Laura"] }, groupB: { names: ["Alice", "Bob", "Neil"] } }, groupX: { groupC: { groupD: { names: ["Steph"] } }, groupE: { names: ["Aaron", "Dave"] } } };
buildList(data);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;