ga-wdi-exercises / project1

[project] GA- Project 1
3 stars 75 forks source link

Issue with looping through nested object #185

Closed ckib16 closed 9 years ago

ckib16 commented 9 years ago

I'm trying to wrap my head around looping through (what I believe to be) a nested object. I want to:

Here is my object that contains the data:

var questionBank = {
      q1: {
        t: 'What is the definition of a "callback"?',
        c1: '1) A piece of executable code that is passed as an argument to other code, which is expected to invoke (or "call back") that executable code at some convenient time.',
        c2: '2) A function written with "call" in it.',
        c3: '3) A function written to be used at a later time.',
        a: '1'
      },
      q2: {
        t: 'This is the question #2 text',
        c1: 'choice 1',
        c2: 'choice 2',
        c3: 'choice 3',
        a: '2'
      },
      q3: {
        t: 'This is the question #3 text',
        c1: 'choice 1',
        c2: 'choice 2',
        c3: 'choice 3',
        a: '3'
      }
    }

The best stack overflow answer I found suggests this:

var findObjectByLabel = function(obj, label) {
    if(obj.label === label) { return obj; }
    for(var i in obj) {
        if(obj.hasOwnProperty(i)){
            var foundLabel = findObjectByLabel(obj[i], label);
            if(foundLabel) { return foundLabel; }
        }
    }
    return null;
};

// which can be called like so

findObjectByLabel(car, "Chevrolet");

http://stackoverflow.com/questions/8085004/iterate-through-nested-javascript-objects

I'll be heading into outcomes but will check in as soon as we are done around 3PM.

RobertAKARobin commented 9 years ago

That StackOverflow answer looks dreadful!

You should be able to just use this:

for(label in questionBank){
  console.log(label); // q1
  console.log(questionBank[label][t]); // 'What is the definition of a "callback"?'
}
ckib16 commented 9 years ago

Ok thanks Robin. We just got done with outcomes, I'll try this now.

ckib16 commented 9 years ago

Robin - I got that to work by slightly modifying. But I can't figure out how to increment over the object so I can act on the first question, then increment to act on the second question etc. I couldn't find anything on how to increment over a for/in loop like you can in a regular for loop.

Maybe change the data structure to a nested array and iterate through that?

for (label in questionBank) {
      console.log(label) // q1
      console.log(questionBank[label].t) // 'What is the definition of a "callback"?'
      console.log(questionBank[label].c1)
      console.log(questionBank[label].c2)
      console.log(questionBank[label].c3)
    }
RobertAKARobin commented 9 years ago

It increments for you. It's just another for loop. If you put console.log(label) inside it you'll see that it's running once for each label in questionBank.

ckib16 commented 9 years ago

Ok - mine is looping thru the entire object before I have a chance to act on any of the individual questions. So it goes straight thru to the last question before I can get a response on the first question.

for (key in questionBank) {
      console.log(key) // q1
      console.log(questionBank[key].t)
      console.log(questionBank[key].c1)
      console.log(questionBank[key].c2)
      console.log(questionBank[key].c3)
      $('#questionDiv > p').html(questionBank[key].t)
      $('#choiceDiv p:eq(0)').html(questionBank[key].c1)
      $('#choiceDiv p:eq(1)').html(questionBank[key].c2)
      $('#choiceDiv p:eq(2)').html(questionBank[key].c3)
    }
RobertAKARobin commented 9 years ago

So instead of a for loop, you need to increment a different way.

Consider something like this:

var myArray = ["a", "b", "c", "d"];
var arrayIndex = 0;

$("button").on("click", function(){
  console.log(myArray[arrayIndex);
  if(arrayIndex == myArray.length){
    console.log("You're done!");
    return true;
  }
  arrayIndex = arrayIndex + 1;
});
ckib16 commented 9 years ago

OK - I got the iteration. But I'm can't figure out how to interpolate the [arrayIndex] into the JQuery line

$('#questionDiv > p').html(questionBank.q'[arrayIndex]'.t)

Full code:

var myArray = ['1', '2', '3']
    var arrayIndex = 0
    $('#nextButton').on('click', function () {
      console.log(myArray[arrayIndex])
      $('#questionDiv > p').html(questionBank.'[arrayIndex]'.t)
      if (arrayIndex === myArray.length) {
        console.log("You're done!")
        return true
      }
      arrayIndex = arrayIndex + 1
    })
RobertAKARobin commented 9 years ago

Hm. I'm not entirely sure what you're going for here, but to interpolate strings:

var name = "Chris";
console.log("Hey there, " + name + "!");
ckib16 commented 9 years ago

My questions & answers #1-3 live under the following structure: questionBank.q1.whatever questionBank.q2.whatever questionBank.q3.whatever

So to call them in JQuery and print them out I've been using

$('#questionDiv > p').html(questionBank.q1.t) $('#questionDiv > p').html(questionBank.q2.t) $('#questionDiv > p').html(questionBank.q3.t)

I need to add the arrayIndex after the letter 'q' to target the correct element of the object.

I tried: $('#questionDiv > p').html(questionBank.q'[arrayIndex]'.t) But JQuery doesn't line strings in the JQuery call.

I'm probably overthinking this. But I don't understand how to simply loop through my object and get to act on each one individually (like a regular array increment).

RobertAKARobin commented 9 years ago

Gotcha. Try this:

.html(questionBank["q" + arrayIndex].t)
ckib16 commented 9 years ago

Nope, Says "parsing error. Unexpected token [ at line... " . Looks like it doesn't like interpolation in JQuery.

$('#questionDiv > p').html(questionBank.['q' + arrayIndex].t)

RobertAKARobin commented 9 years ago

It's because you have a . after questionBank. It should be questionBank[

ckib16 commented 9 years ago

Yes,but I think I need the . to get to questionBank.q1.t

That's what worked for me as hard-coded examples

RobertAKARobin commented 9 years ago

questionBank[q1] is the same as questionBank.q1

ckib16 commented 9 years ago

OK. Now getting Uncaught TypeError: Cannot read property 't' of undefined in Chrome.

Trying to move around the statement to see if scope is the issue.

RobertAKARobin commented 9 years ago

This is progress. See what questionBank['q' + arrayIndex] is.

ckib16 commented 9 years ago

It returns this to the console

[p, prevObject: m.fn.init[1], context: document, selector: "#questionDiv > p"]

ckib16 commented 9 years ago

Ok - I called uncle and recoded the data into arrays. Much easier to call and iterate through. Thanks for the help!

RobertAKARobin commented 9 years ago

Woooo!