简体   繁体   中英

How to access values of nested arrays?

I have an array inside an array of objects that I want to retrieve a property from. I've accomplished it here , but it seems clunky. Is there a better way of looping through each StaffList array within each room?

window.onload = getInitials;
var data = {
    "room" : [
        {
            "id" : 1,
            "StaffList": [
                {                  
                  "inroom": true,                  
                  "initials": "MG"
                },
                {
                  "inroom": false,
                  "initials": "CT"
                },
                {
                  "inroom": true,
                  "initials": "MS"
                }
            ]
        },
        {
            "id" : 2,
            "StaffList": [
                {                  
                  "inroom": true,                  
                  "initials": "MG"
                },
                {
                  "inroom": false,
                  "initials": "CT"
                },
                {
                  "inroom": true,
                  "initials": "MS"
                },
                {
                  "inroom": true,
                  "initials": "MA"
                }
            ]
        }   

    ]
}

function getInitials() {
    var len = data.room.length;
    for(i = 0; i < len; i++) {
        var staffArray = data.room[i].StaffList;
        var room = data.room[i].id;
        if( staffArray != null ) {
            var allStaff = staffArray.filter(function(person) {
                if ( person.initials ) {
                    var inits = person.initials;
                    setInitials(room, inits);
                }
            });
        }
    }
}

function setInitials(room, initials) {
    //get element by ID
    //var staffContainer = $('#div' + room);
    var staffContainer = document.getElementById('div' + room);
    if(staffContainer != null) {
        //create new div to append
        var newDiv = document.createElement('div');
        newDiv.innerHTML = initials; 
        //append newly created <div>
        staffContainer.append(newDiv);
    }
}

You could use some forEach :

data.room.forEach(function(room) {
  room.StaffList.forEach(function(person) {
    setInitials(room.id, person.initials);
  });
});

Here, we first loop through each room and then through each person of the StaffList . Since the second forEach is inside the first one, we have access to its scope (through a closure, see How do JavaScript closures work? ). Then we can just employ our new parameters, room and person , for setInitials .

Notice how there was no use of a var statement. When you don't need to create a state (a variable), don't do it. Fewer states generally also mean fewer errors. However, in your setInitials function, the use of states for the container and the new div is the way to go.

PS: Something else about your code tickles me. Your variable room is not a room object, but an id. It's misleading! Make sure to use the right name for the right thing. Here, if you want a state to store the id of a room, name it roomId .


You said in a comment that you also wanted to add a class on the created div if the inroom value is true (by the way, you should CamelCase it). In that case, you could pass it as third parameter of setInitials , then add the class according to its value in the body of the function.

Without any real details on how you want to sort things: just use sort with a sorting function, it's what it was designed for (noting that sort() is in-place , it modifies the array that's being sorted instead of merely generating a new array as function output):

var data = ....;

// preprocess your data
data.rooms.forEach(function(room) {
  doSomethingToYour(room);
});

// sort stafflists per room, which we can only do
// after your preprocessing has completed.
data.rooms.forEach(function(room) {
  room.StaffList.sort(function(a,b) {
    a = a.initials;
    b = b.initials;
    return a<b? -1 : a>b ? 1 : 0;
  });
});

// optionally, we can sort the rooms now, if those
// relied on ordered StaffList. If not, we could have
// sorted them at any point.
data.rooms.sort(function(a,b) {
  return b.id - a.id;
}); 

A couple suggestions:

Use nested loops to retrieve nested array values

This one's pretty simple: your outer loop will traverse the array of rooms, while your inner loop will traverse the array of staff for each room.

In the example code below, my outer loop is a while loop and my inner is a for , but you can of course accomplish it using whichever method you prefer.

function getInitials() {
  var len = data.room.length;
  while (len--) {
    var staffArray = data.room[len].StaffList;
    var room = data.room[len].id;
    for (var i = 0; i < staffArray.length; i++) {
      var person = staffArray[i];
      if (person.initials) {
        setInitials(room, person.initials);
      }
    }
  }
}

function setInitials(room, initials) {
  var staffContainer = document.getElementById("div" + room);
  if (staffContainer != null) {
    var newDiv = document.createElement("div");
    newDiv.innerHTML = initials;
    staffContainer.appendChild(newDiv);
  }
}

Reduce unnecessary DOM queries

I recommend caching an array of references to the desired divs, so you can just use the div's index in the array to retrieve it.

I would do this by populating the array of divs in the outer loop, then passing the relevant div as the first argument to setInitials()

 function getInitials() { var len = data.room.length; var roomDivs = []; while (len--) { var staffArray = data.room[len].StaffList; var roomId = data.room[len].id; roomDivs[roomId] = document.getElementById("div" + roomId); for (var i = 0; i < staffArray.length; i++) { var person = staffArray[i]; if (person.initials) { setInitials(roomDivs[roomId], person.initials); } } } } function setInitials(staffContainer, initials) { if (staffContainer != null) { var newDiv = document.createElement("div"); newDiv.innerHTML = initials; staffContainer.appendChild(newDiv); } } var data = { "room": [{ "id": 1, "StaffList": [{ "inroom": true, "initials": "MG" }, { "inroom": false, "initials": "CT" }, { "inroom": true, "initials": "MS" }] }, { "id": 2, "StaffList": [{ "inroom": true, "initials": "MG" }, { "inroom": false, "initials": "CT" }, { "inroom": true, "initials": "MS" }, { "inroom": true, "initials": "MA" }] } ] } getInitials(); 
 #div1 { background-color: burlywood; } #div2 { background-color: crimson; } div { height: auto; width: 50px; padding: 3px; margin: 2px; } 
 <div id="div1"></div> <div id="div2"></div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM