1

I have a JSON object like so:

{
  "workouts":
  [
    {
      "title": "Full Body",
      "exercises":
      [
        {
          "name": "Push Ups",
          "duration": 3,
          "break": 3
        },
        {
          "name": "Squats",
          "duration": 3,
          "break": 3
        },
        {
          "name": "Running in Place",
          "duration": 3,
          "break": 3
        }
      ]
    },
    {
      "title": "God Legs",
      "exercises":
      [
        {
          "name": "Running in Place (High Knees)",
          "duration": 3,
          "break": 3
        },
        {
          "name": "Squats",
          "duration": 3,
          "break": 3
        },
        {
          "name": "Clams",
          "duration": 3,
          "break": 3
        }
      ]
    },
    {
      "title": "Morning Stretch",
      "exercises":
      [
        {
          "name": "Downward Dog",
          "duration": 3,
          "break": 3
        },
        {
          "name": "Face Plant",
          "duration": 3,
          "break": 3
        },
        {
          "name": "Warrior",
          "duration": 3,
          "break": 3
        }
      ]
    }
  ]
}

I can loop through the titles and append them to the body, now I would like to loop through each object contained in the "exercises" array and print out each value: name, duration and break, per object. I am not having much success and I wonder if I should change my JSON structure or if I am making some silly mistake in my loops. I am using Firebase by the way, no AJAX calls or such like.

JavaScript:

// Initialize firebase.
firebase.initializeApp(config);

var dbRef = firebase.database().ref().child("workouts");

// Sync with Firebase in real time.
dbRef.on("value", snap =>
{
  var workouts = snap.val();

  // HAVE A LOOP FOR EVERY ARRAY INJSON.
  for (var i = 0;  i < workouts.length; i++)
  {
    window.alert(i + workouts[i].title); // Works fine.

    var obj = workouts[i].exercises;
    for (obj in workouts)
    {
      alert(obj.name); // Returns undefined for each object.
    }
  }
});
2
  • Remove var obj = workouts[i].exercises; and replace for (obj in workouts) with for (obj in workouts[i].exercises). You're overwriting the obj variable and looping over the wrong array unless I'm misstaken. Commented Oct 26, 2017 at 14:13
  • 1
    Doing UI based on JSON objects is so nice with something like Aurelia btw. Just an aside. Commented Oct 26, 2017 at 14:14

4 Answers 4

2

Using for..in to iterate through arrays generally isn't a great idea in JS. Try using Array.forEach to go through all items in the array instead:

var obj = workouts[i].exercises;
obj.forEach(function(exercise) {
    alert(exercise.name);
});
Sign up to request clarification or add additional context in comments.

1 Comment

That is great! Thank you! I was looking through forEach docs online, but being a n00b was kinda lost in how to use them correctly.
2

Try this

var obj = workouts[i].exercises;
for (index in obj) {
    console.log(obj[index].name);
}

It's a bit of logical fault here. You want to get the exercise name, not the workout name.

Comments

1

As long as more modern JS is ok, I would probably suggest you use array.prototype.forEach with a callback in both of your loops.

const data = {"workouts":[{"title":"Full Body","exercises":[{"name":"Push Ups","duration":3,"break":3},{"name":"Squats","duration":3,"break":3},{"name":"Running in Place","duration":3,"break":3}]},{"title":"God Legs","exercises":[{"name":"Running in Place (High Knees)","duration":3,"break":3},{"name":"Squats","duration":3,"break":3},{"name":"Clams","duration":3,"break":3}]},{"title":"Morning Stretch","exercises":[{"name":"Downward Dog","duration":3,"break":3},{"name":"Face Plant","duration":3,"break":3},{"name":"Warrior","duration":3,"break":3}]}]}

data.workouts.forEach(workout => {
  workout.exercises.forEach(exercise => console.log(workout.title, '---', exercise.name));
});

For more backwards compatibility you could do nested loops like so:

const data = {"workouts":[{"title":"Full Body","exercises":[{"name":"Push Ups","duration":3,"break":3},{"name":"Squats","duration":3,"break":3},{"name":"Running in Place","duration":3,"break":3}]},{"title":"God Legs","exercises":[{"name":"Running in Place (High Knees)","duration":3,"break":3},{"name":"Squats","duration":3,"break":3},{"name":"Clams","duration":3,"break":3}]},{"title":"Morning Stretch","exercises":[{"name":"Downward Dog","duration":3,"break":3},{"name":"Face Plant","duration":3,"break":3},{"name":"Warrior","duration":3,"break":3}]}]};

for (let i = 0, len = data.workouts.length; i < len; i++) {
  let exercises = data.workouts[i].exercises;
  for (let x = 0, l = exercises.length; x < l; x++) {
    console.log(data.workouts[i].title, '---', data.workouts[i].exercises[x].name);
  }
}

Comments

1

Tried to write solution with just map() operator

var mainObj = {
  "workouts":
  [
{
  "title": "Full Body",
  "exercises":
  [
    {
      "name": "Push Ups",
      "duration": 3,
      "break": 3
    },
    {
      "name": "Squats",
      "duration": 3,
      "break": 3
    },
    {
      "name": "Running in Place",
      "duration": 3,
      "break": 3
    }
  ]
},
{
  "title": "God Legs",
  "exercises":
  [
    {
      "name": "Running in Place (High Knees)",
      "duration": 3,
      "break": 3
    },
    {
      "name": "Squats",
      "duration": 3,
      "break": 3
    },
    {
      "name": "Clams",
      "duration": 3,
      "break": 3
    }
  ]
},
{
  "title": "Morning Stretch",
  "exercises":
  [
    {
      "name": "Downward Dog",
      "duration": 3,
      "break": 3
    },
    {
      "name": "Face Plant",
      "duration": 3,
      "break": 3
    },
    {
      "name": "Warrior",
      "duration": 3,
      "break": 3
    }
  ]
}
  ]
}

mainObj["workouts"].map(obj => obj["exercises"].map(exercises => console.log(obj["title"]+"-->"+exercises["name"])))

2 Comments

That is quite awesome!
You can also use "dot notation" so you can use autocompletion properties: mainObj.workouts.map(obj => obj.exercises.map(exercises => console.log(obj.title+"-->"+exercises.name)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.