列出所有嵌套属性及其在包含对象中的完整路径
List all nested properties with their full path in the containing object
我有一些名称数组存储在嵌套的 JSON 中,如下所示:
{
"groupZ": {
"names": [
"Steve",
"Henry"
]
},
"groupY": {
"groupA": {
"names": [
"Laura"
]
},
"groupB": {
"names": [
"Alice",
"Bob",
"Neil"
]
}
},
"groupX": {
"groupC": {
"groupD": {
"names": [
"Steph"
]
}
},
"groupE": {
"names": [
"Aaron",
"Dave"
]
}
}
}
我想弄清楚如何生成所有名称的列表,并为每个名称添加完整的组路径,所以它最终是这样的:
- groupZ - 史蒂夫
- groupZ-亨利
- Y 组 - A 组 - 劳拉
- 组 Y - 组 B - 爱丽丝
- 组 Y - 组 B - 鲍勃
- Y 组 - B 组 - 尼尔
- groupX - groupC - groupD - 斯蒂芬
- X组-E组-亚伦
- X 组 - E 组 - 戴夫
每个级别的组名都是唯一的,但除此之外可以任意命名。我知道我需要递归调用一个函数,该函数在找到 "names" 数组时停止,传递一个字符串以在每次递归时添加到前缀中,但遇到了真正的麻烦。到目前为止,这是我的代码:
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 结构,但我确信这是可能的。感谢任何可以提供帮助的人!
这对我有用:
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);
是的,你很接近。您只需要确保将连接的组名称(以前的 + 当前的)传递给递归函数。
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, '');
我想你也想 return 这最终作为一个列表,这需要更多的努力。
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]);
}
您可以采用一个数组作为路径并调用不带该参数的函数,因为它会被检查,如果没有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);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我有一些名称数组存储在嵌套的 JSON 中,如下所示:
{
"groupZ": {
"names": [
"Steve",
"Henry"
]
},
"groupY": {
"groupA": {
"names": [
"Laura"
]
},
"groupB": {
"names": [
"Alice",
"Bob",
"Neil"
]
}
},
"groupX": {
"groupC": {
"groupD": {
"names": [
"Steph"
]
}
},
"groupE": {
"names": [
"Aaron",
"Dave"
]
}
}
}
我想弄清楚如何生成所有名称的列表,并为每个名称添加完整的组路径,所以它最终是这样的:
- groupZ - 史蒂夫
- groupZ-亨利
- Y 组 - A 组 - 劳拉
- 组 Y - 组 B - 爱丽丝
- 组 Y - 组 B - 鲍勃
- Y 组 - B 组 - 尼尔
- groupX - groupC - groupD - 斯蒂芬
- X组-E组-亚伦
- X 组 - E 组 - 戴夫
每个级别的组名都是唯一的,但除此之外可以任意命名。我知道我需要递归调用一个函数,该函数在找到 "names" 数组时停止,传递一个字符串以在每次递归时添加到前缀中,但遇到了真正的麻烦。到目前为止,这是我的代码:
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 结构,但我确信这是可能的。感谢任何可以提供帮助的人!
这对我有用:
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);
是的,你很接近。您只需要确保将连接的组名称(以前的 + 当前的)传递给递归函数。
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, '');
我想你也想 return 这最终作为一个列表,这需要更多的努力。
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]);
}
您可以采用一个数组作为路径并调用不带该参数的函数,因为它会被检查,如果没有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);
.as-console-wrapper { max-height: 100% !important; top: 0; }