0

I have a huge object that contains the entire ESV Bible. I am trying to get a random book of the Bible whenever I press a button. Here is a small sample of the object.

var esvObject = {

 "Genesis": {

    "1": {}
    "2": {}
    "3": {}

   },
 "Exodus": {

    "1": {}
    "2": {}
    "3": {}

   }

}

Here is the code that I am using to get a random book.

var randNum = Math.floor(Math.random() * 66);

var randBook = esvObject[randNum];

var output = randBook;

I would expect this to work, but the output I always get is "undefined," where as I would like the output to be "Genesis" or "Exodus" etc. Getting the random number works, but if

randNum = 1

then

randBook = esvObject[1]

the output returns as "undefined" and I don't know why.

Caleb
  • 21
  • 5

5 Answers5

1

Well the reason you get undefined is that your object is of the structure:

let esvObject = {
   bookName: {
      1 : {}
   }
}

Using bracket [] notation on a javascript object finds the matching key for the name and returns it's value. In your top level object (the one with bookNames for keys), you have to use a valid book name like Genesis. To do so, leverage the Object.keys function of javascript to get an array of all the keys in your object.

You can then use [] notation, which has a different semantic on arrays.

let books = Object.keys(esvObject); // ["Genesis", "Exodus", ...]
let randomKey = books[randNum] // this is an array, so index access works
let book = esvObject[randomKey]  // matches on the bookname

And to tie it all together, esvObject["Genesis"][1] would have been valid because the object stored as "Genesis" has a property 1

mistahenry
  • 8,554
  • 3
  • 27
  • 38
0

You are generating random number. And then trying to pick property using that number.

But you object has properties Genesis and Exodus not 1 or 20 etc. What you need to do is Object.getOwnPropertyNames(esvObject) that will give you array of the property names. In this case ['Genesis', 'Exodus'] and then you need to pick random element from that array

Suxino
  • 169
  • 5
0

It would not work because it does not know that the first book is named "Genesis". To be able to use numbers from the random function you will need to use array from the keys of the object

var keys = esvObject.keys( obj );
randBookKey = keys[randNum]
randBook = esvObject[randBookKey]
Simmol
  • 1
  • 1
  • 2
0

esvObject (as you show it) does not have any integer keys. So you need to select a random (existing) key instead:

esvObject[Object.keys(esvObjects)[Math.floor(Math.random() * 66)]]
idmean
  • 14,540
  • 9
  • 54
  • 83
  • I'm not sure, but I think I have tried that before, and the result was [object Object] – Caleb Jan 30 '19 at 12:41
  • @Caleb Well, this will return an object. If you covert it to a string you'll get `[object Object]`. That shouldn’t come in surprising. If you just want the name of the book only use `Object.keys(esvObjects)[Math.floor(Math.random() * 66)]` – idmean Jan 30 '19 at 12:43
  • The name of the book will output as a string though right? So if I assign a variable to `esvObject[Object.keys(esvObjects)[Math.floor(Math.random() * 66)]]`, it will output as a string, right? – Caleb Jan 30 '19 at 12:45
  • No, `Object.keys(esvObjects)[Math.floor(Math.random() * 66)]` gives you a string. One of the keys of your objects, i.e. a name of a book. If you use that string to access `esvObject`, you’ll get whatever is assigned to this property. In your case, `{ "1": {} "2": {} "3": {} }` (note that you missed commas) – idmean Jan 30 '19 at 12:49
  • I did this `randBook = esvObject[Object.keys(esvObject)[Math.floor(Math.random() * 66)]]` and the output was [object Object] – Caleb Jan 30 '19 at 13:20
0

You're confusing accessing an array with accessing an object.

An array:

arr = ["genesis", "exodus"]

is accessed like this:

arr[0] // genesis

An object:

obj = { "genesis" : "foo", "exodus" : "bar"}

is accessed like this:

obj["genesis"] // foo

To achieve what you want to do, see Access non-numeric Object properties by index?

andydavies
  • 3,081
  • 4
  • 29
  • 35