Home > Enterprise >  Traversing through indented arrays in javascript
Traversing through indented arrays in javascript

Time:12-17

I have a javascript object as follows :

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

};

I want to print/get each of the node value [headmaster, headmastress,..] and their corresponding child values. I tried various methods like looping through the array using a for loop, recurse etc, but unfortunately I am not able to get any value out of the nodes. Please help.

e.g : I used this :

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

}

The values can be shown in this format : 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 - ...

CodePudding user response:

You could remove known keys from the object and get the type hierarchy then iterate the property and return the tupel of type, name, subject and key only if type exists.

const
    getValues = (object, type) => [
        ...(type ? [[type, object.name, object.subject || '', 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; }

CodePudding user response:

I would suggest restructuring so that the subordinates are always accessed with the same key, and thus can be visited very simply. I also made it so every node is a person, there's no object at the top that isn't a person. I left the variable name, but it now refers to Dumbledore directly.

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

CodePudding user response:

Given the data structure:

a) I assume that there will be only one array in each type of "title", and
b) that array will contain a list of objects of a similar structure as it's parent

It's possible ...

  1. to use for..of in order to
  2. iterate through each key on an object, and add them to a string. Because there are arrays that contains objects,
  3. I can loop through them, and
  4. do a recursive loop.

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

I would honestly split up hogwartsHierarchy into smaller bits, following a kind of database structure, where primary_key is unique for each individual. These arrays doesn't make much sense, until you look at the variable professors and how their respectively belongs_to key corresponds to the standbyprofessors, where you can see that "Horace Slughorn" belongs to "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
  },
];
  • Related