遍历javascript中的缩进数组
Posted
技术标签:
【中文标题】遍历javascript中的缩进数组【英文标题】:Traversing through indented arrays in javascript 【发布时间】:2022-01-19 21:42:25 【问题描述】:我有一个 javascript 对象如下:
let hogwartsHeirarchy =
Headmaster: [
name: "Professor Dumbledore",
key: 1,
Headmistress: [
name: "Minerva McGonagall",
key: 2,
StandByProfessor: [
name: "Rubeus Hagrid",
subject: "Potions Master",
key: 3,
Professor: [
name: "Horace Slughorn", key: 4 ,
name: "Severus Snape", key: 4 ,
],
,
name: "Alastor Moody",
subject: "Defense Against the Dark Arts",
key: 3,
Professor: [
name: "Remus Lupin", key: 4 ,
name: "Gilderoy Lockhart", key: 4 ,
],
,
],
,
],
,
],
;
我想打印/获取每个节点值 [headmaster, headmastress,..] 及其对应的子值。我尝试了各种方法,例如使用 for 循环、递归等遍历数组,但不幸的是我无法从节点中获取任何值。请帮忙。
例如:我用过这个:
printArray(hogwartsHeirarchy);
function printArray(arr)
for(var i = 0; i < arr.length; i++)
if(arr[i] instanceof Array)
console.log("true: ");
console.log("intermediate one : ",arr[i]);
printArray(arr[i]);
else
console.log("final one : ",arr[i]);
值可以用这种格式显示:
Headmaster - name : Professor Dumbledore, key : 1
.
.
StandByProfessor - name : Robeus Hagrid, subject : Potion Master, key : 3
StandByProfessor - name : Alastor Moody, subject : Defence against the dark arts, key : 3
.
.
Professor - ...
Professor - ...
Professor - ...
Professor - ...
【问题讨论】:
请添加想要的结果。看起来怎么样?hogwartsHeirarchy
是一个对象而不是数组。 length
不是对象的属性,因此它将返回 undefined
,因此您的 for 循环不会发生迭代。
@peineary .. 我是 javascript 新手,无论如何请帮助遍历这个对象/数组。
@Nina .. 我已经编辑了我的问题,请检查。
为什么不使用具有相同键的数据结构来嵌套对象而不是未知键名?
【参考方案1】:
您可以从对象中删除已知键并获取类型层次结构,然后迭代属性并仅在类型存在时返回类型、名称、主题和键的元组。
const
getValues = (object, type) => [
...(type ? [`$type - name : $object.name, $object.subject ? `subject : $object.subject, ` : ''key : $object.key`] : []),
...Object
.keys(object)
.filter(k => !['name', 'subject', 'key'].includes(k))
.flatMap(k => object[k].flatMap(o => getValues(o, k)))
],
hogwartsHierarchy = Headmaster: [ name: "Professor Dumbledore", key: 1, Headmistress: [ name: "Minerva McGonagall", key: 2, StandByProfessor: [ name: "Rubeus Hagrid", subject: "Potions Master", key: 3, Professor: [ name: "Horace Slughorn", key: 4 , name: "Severus Snape", key: 4 ] , name: "Alastor Moody", subject: "Defense Against the Dark Arts", key: 3, Professor: [ name: "Remus Lupin", key: 4 , name: "Gilderoy Lockhart", key: 4 ] ] ] ] ;
console.log(getValues(hogwartsHierarchy));
.as-console-wrapper max-height: 100% !important; top: 0;
【讨论】:
感谢@Nina 的帮助。这段代码看起来有点复杂,而且对我的 javascript 理解来说非常先进。您是否可以按照问题本身所述的格式显示数据?【参考方案2】:我建议进行重组,以便始终使用相同的键访问下属,从而可以非常简单地访问。我也做到了,所以每个节点都是一个人,顶部没有一个不是人的对象。我留下了变量名,但现在它直接引用了 Dumbledore。
let hogwartsHeirarchy =
name: "Professor Dumbledore",
role: "Headmaster",
key: 1,
subordinates: [
name: "Minerva McGonagall",
role: "Headmistress",
key: 2,
subordinates: [
name: "Rubeus Hagrid",
role: "StandByProfessor",
subject: "Potions Master",
key: 3,
subordinates: [
name: "Horace Slughorn", key: 4, role: "Professor" ,
name: "Severus Snape", key: 4, role: "Professor" ,
],
,
name: "Alastor Moody",
role: "StandByProfessor",
subject: "Defense Against the Dark Arts",
key: 3,
subordinates: [
name: "Remus Lupin", key: 4, role: "Professor" ,
name: "Gilderoy Lockhart", key: 4, role: "Professor" ,
],
,
],
,
],
;
function visitStaff(staffMember)
if (staffMember.subordinates)
for (const subordinate of staffMember.subordinates)
visitStaff(subordinate);
console.log("Staff member:", staffMember);
visitStaff(hogwartsHeirarchy);
在设置数据结构时,重要的是要考虑如何访问它,以及它的定义部分是什么。在这种情况下,有人是节点,还有(从属)关系,是图的边。
在您的原始代码中,您有一个对象 Headmaster: [...]
— 它代表什么?是一个人吗?不;是关系吗?有点,但没有。它定义了关于 Dumbledoor 的一些东西,即他是校长,但没有定义他是 of 的校长是谁或什么。所以它实际上只是描述了 Dumbledoor 的角色/职位,所以它作为个人的财产更有意义。它作为一个对象是多余的。
它有助于对齐您的对象,使它们都代表某些东西。您应该能够描述每个对象和数组是什么。
【讨论】:
@1jo1,非常感谢您简化了结构和解释。这些节点现在更加不言自明,并且采用了正确可读的格式。 编辑:@1jo1,刚刚检查了您提供的解决方案以及解释。谢谢你。最干净的解决方案。【参考方案3】:给定数据结构:
a) 我假设每种“标题”类型中只有一个数组,并且 b) 该数组将包含与其父级结构相似的对象列表
有可能……
-
使用
for..of
以便
遍历对象上的每个键,并将它们添加到字符串中。因为存在包含对象的数组,
我可以遍历它们,并且
通过让方法调用自身来执行递归循环。
const hogwartsHierarchy = Headmaster: [ name: "Professor Dumbledore", key: 1, Headmistress: [ name: "Minerva McGonagall", key: 2, StandByProfessor: [ name: "Rubeus Hagrid", subject: "Potions Master", key: 3, Professor: [ name: "Horace Slughorn", key: 4 , name: "Severus Snape", key: 4 ] , name: "Alastor Moody", subject: "Defense Against the Dark Arts", key: 3, Professor: [ name: "Remus Lupin", key: 4 , name: "Gilderoy Lockhart", key: 4 ] ] ] ] ;
function printAllWithChilds(obj, prevProp)
let listItem = (prevProp) ? ' -- ' + prevProp : '';
for (const property in obj) // 1
if (obj[property] instanceof Array)
obj[property].forEach((child_obj) => // 3
listItem += printAllWithChilds(child_obj, property); // 4
);
else
listItem += `, $property: $obj[property]`; // 2
return listItem;
let listStr = printAllWithChilds(hogwartsHierarchy);
console.log(listStr);
我会诚实地将hogwartsHierarchy
拆分成更小的部分,遵循一种数据库结构,其中primary_key
对于每个人都是唯一的。这些数组没有多大意义,直到您查看变量professors
以及它们各自的belongs_to
键如何对应于standbyprofessors
,您可以在其中看到“Horace Slughorn”属于“Rubeus Hagrid”。
const headermaster =
name: "Professor Dumbledore",
primary_key: 1
;
const headmistress =
name: "Minerva McGonagall",
primary_key: 2,
belongs_to: 1
;
const standbyprofessors = [
name: "Rubeus Hagrid",
subject: "Potions Master",
primary_key: 3,
belongs_to: 2
,
name: "Alastor Moody",
subject: "Defense Against the Dark Arts",
primary_key: 4,
belongs_to: 2
];
const professors = [
name: "Horace Slughorn",
primary_key: 5,
belongs_to: 3
,
name: "Severus Snape",
primary_key: 6,
belongs_to: 3
,
name: "Remus Lupin",
primary_key: 7,
belongs_to: 4
,
name: "Gilderoy Lockhart",
primary_key: 8,
belongs_to: 4
,
];
【讨论】:
感谢@Rickard 的所有解释和解决方案。我个人希望按照您的解释划分这个基于大型节点的结构,但是,客户端仅按照问题中的描述以特定格式向我们提供数据。我也尝试过仅使用递归方法进行初始解析,我们是否可以期望递归比 FFire 和 Lina 讨论的方法更高效? FFire 的代码看起来和我的一样高效,因为我的代码只循环一次。 Nina 包含keys, filter, includes and flatmap
(两次),它们本身都是循环,这表明代码不够充足。【参考方案4】:
基于1j01 对象模型:
const hogwartsHeirarchy =
name: "Professor Dumbledore", role: "Headmaster", key: 1,
subordinates: [ name: "Minerva McGonagall", role: "Headmistress", key: 2,
subordinates: [
name: "Rubeus Hagrid", role: "StandByProfessor", subject: "Potions Master", key: 3,
subordinates: [
name: "Horace Slughorn", key: 4, role: "Professor" ,
name: "Severus Snape", key: 4, role: "Professor" ],
name: "Alastor Moody", role: "StandByProfessor", subject: "Defense Against the Dark Arts", key: 3,
subordinates: [
name: "Remus Lupin", key: 4, role: "Professor" ,
name: "Gilderoy Lockhart", key: 4, role: "Professor" ]]];
const visitStaff = (staffMember) =>
const iter = (obj) =>
const name, role, key, subordinates = obj;
const subject = obj.subject ? `, subject : $obj.subject` : '';
const line = `$role - name : $name$subject, key : $key`;
const sublines = (Array.isArray(subordinates)) ? subordinates.flatMap(iter) : [];
return [line, ...sublines];
return iter(staffMember).join('\n');
console.log(visitStaff(hogwartsHeirarchy));
.as-console-wrapper max-height: 100% !important; top: 0;
【讨论】:
非常感谢@FFire,这看起来像是一个完整的解决方案!我对javascript中的flatmap等属性仍然很陌生。 javascript中是否有任何适当的参考/库可以使这些任务自动化?现在,我们正在手动解析/循环每个节点。 @RahulK,没有外部库,比如lodash等,只有vanila JS以上是关于遍历javascript中的缩进数组的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 javascript 中的 Promise 遍历问题数组中的每个项目
JavaScript中的数组遍历forEach()与map()方法以及兼容写法