遍历 javascript 中的缩进数组

Traversing through indented arrays in javascript

我有一个 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 },
              ],
            },
          ],
        },
      ],
    },
  ],
};

我想要 print/get 每个节点值 [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 - ...

您可以从对象中删除已知键并获取类型层次结构,然后仅当类型存在时才迭代 属性 和 return 类型、名称、主题和键的元组。

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; }

我建议重组,以便始终使用相同的密钥访问下级,从而可以非常简单地访问。我还做到了,所以每个节点都是一个人,顶部没有不是人的对象。我留下了变量名,但它现在直接引用 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 的 role/job 头衔,因此作为此人的 属性 更有意义。它作为一个对象是多余的。

它有助于对齐您的对象,使它们都代表某种东西。您应该能够描述每个对象和数组是什么。

给定数据结构:

a) 我假设每种类型的“标题”中只有一个数组,并且
b) 该数组将包含与 parent

结构相似的 object 列表

有可能...

  1. 使用for..of以便
  2. 遍历 object 上的每个键,并将它们添加到字符串中。因为有数组包含objects,
  3. 我可以遍历它们,并且
  4. 通过让方法调用自身来执行递归循环。

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”属于“鲁伯·海格”。

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
  },
];

基于 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; }