Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat
Use # for a multi-dimensional table? - Gideros Forum

#### Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

# Use # for a multi-dimensional table?

Member
edited November 2017
This is a pretty simple question, but I just don't know the answer. I’m not sure how to use “#” in a for loop.

I have a 2 dimensional array, questions(a)(b). The first index (a) indicates the number of the question. The first element of the second index (b) is the text of the question (which is a multiple choice question) and the following elements are the possible answers.

For example (This is for the sixth question in the table.)
questions[6] [question] = “What year was the Declaration of Independence signed?”
questions[6] [correctAnswer] = “1776”
questions[6] [wrongAnswer1] = “1917”
questions[6] [wrongAnswer2] = “1812”
questions[6] [wrongAnswer3] = “1865”
questions[6] [wrongAnswer4] = “1945”

I want to run these questions through a for loop based solely on the first index. That is, I want the loop to do something to the first question, then the same thing to the second and so on. If it was a one dimensional array, I would just do for i=1,#questions, with #questions returning the number of questions. However, I suspect #questions counts all of the elements in the table. If each question has 1 question and 4 answers (i.e, the second index would have possibilities 1-5) #questions would return a number that is 5 times the number of questions in the table. Is this correct?

If I knew for sure that every question had 5 elements as in the example above, I could just use #questions/5 instead of #questions. But some questions only have 3 choices, not 4, so there’s no way I could do that.

Is there a way to get the number of elements in each of the dimensions of the table?
For example (a is the number of elements in first dimension and b is the number of elements in the second dimension):
for i=1,a do
for j=1,b do
code to be performed
end
end

That is, what can I use in my code in place of a and b to loop through the number of items in each dimension of the table?

## Comments

• Maintainer
assuming you have questions in a table from 1 to n, you can use # to find the number of entries in the table. Then assuming each question has a sub-table that doesn't use numbers to index it then you can use in pairs. Here is an example...
 ```for loop=1,#questions do local question=questions[loop] for key,value in pairs(question) do print(key,value) end end```

Likes: antix

+1 -1 (+1 / -0 ) Share on Facebook
• Member
Thanks, SinisterSoft.

Likes: SinisterSoft

+1 -1 (+1 / -0 ) Share on Facebook
• Maintainer
• Member
edited November 2017
@rpallen just a couple of notes from my personal experience to integrate SinisterSoft's answer:

pairs is wonderful, but "slow". maybe you won't notice that in this app because you run it only once in a while. However watch out for performance if you need to "abuse" of it also note that pairs outcome may vary its order (somewhere someone made a pairsByKeys lua function to avoid this, but it's even slower because it has to check and order elements before returning them).
Usually nested for loops are performance killers, but sometimes you can't avoid this.

However the fastest way to operate on tables with for loops is using numerical indices.
for loop=1,#questions do

The lenght operator # works only on strings (ie. to know how many chars are there) and on tables with numerical indices.
You may experience strange behaviours -like 0 counts- if your table has string indices (or mixed string and number indices).

I think that I personally would write my questions and answers with numerical indices, in a way that the question and the correct answer are always in the same place (index), and my app knows that.
ie:

questions[6] = {
“What year was the Declaration of Independence signed?”,
“1776”,
“1917”,
“1812”,
“1865”,
“1945”
}

[1] the question
[2] the correct answer
how many answers are there = #questions[6] - 1
(where the 1 we are taking away is the first table entry, because it is the question in this scenario, but it could also have been the last..., so that questions[6][ #questions[6] ] was the question)

or

questions[6] = {
q = “What year was the Declaration of Independence signed?”,
a = {
“1776”,
“1917”,
“1812”,
“1865”,
“1945”
}
}

[q] the question
[a] the answers, [a][1] is the correct one.
how many answers are there = #questions[6][a]

Both ways would enable to check how many answers are there with the lenght operator, then I would mix the answers on a random basis when placing them on screen (but here I suppose I would still need for and maybe pairs. Just once though, when I need to place the answers on screen) .

Another option would be to add a "correct answer" value to each questions entry:
questions[6]["c"] = 1 (assuming that the right answer is on index 1) to tell the app which answer is correct (which index inside "a" contains the right answer), in this way you won't need to mix the answers, because you can write them already in the order you like. But everytime you play, the answers would be in the same position.

edit: i forgot to answer this
If each question has 1 question and 4 answers (i.e, the second index would have possibilities 1-5) #questions would return a number that is 5 times the number of questions in the table. Is this correct?
no, assuming you have questions in a table from 1 to n (using numerical indices), # would return n .
If you have one (or more) sub-tables their value would always count 1 each (# just counts each entry at the "table level" you ask. see my examples before)
• Member
edited November 2017
Thanks, pie.

I do use two randomizing functions, one to randomize the questions and another to randomize the answers. I need 2 functions because they need to operate a bit differently. The one for the answers has to both randomize the order of the answers and keep track of the position of the correct answer. The randomizer for the questions only needs to randomize the order of the questions.
• Member
edited November 2017
@rpallen I thought that you could even build your question as:

questions[6] = {
q = “What year was the Declaration of Independence signed?”,
a = {
{“1776”},
“1917”,
“1812”,
“1865”,
“1945”
}
}

in this way you could use the same function for both "randomize" operations, without the need to keep track of the correct answer position.
You may get the correct answer just looking at the data type:
 ```local output for n=1, #questions[6][a] do if type(questions[6][a][n]) == 'table' then --this is the correct answer output = questions[6][a][n][1] else --this is a wrong answer output = questions[6][a][n] end end```
• Member
edited November 2017
What about just keeping track of which question is correct?
 ```questions = { { question = “What year was the Declaration of Independence signed?”, answers = { {text = “1776”, correct = true}, {text = “1917”, correct = false}, {text = “1812”, correct = false}, {text = “1865”, correct = false}, {text = “1945”, correct = false}, }, }, -- more questions here }```
• Member
edited November 2017
Got bored eating breakfast so this is kind of what I was eluding to above..
 ```local questions = { { question = "What year was the Declaration of Independence signed?", answers = { "1776", -- always put the correct answer first in the list "1917", "1812", "1865", "1945", }, order = {}, -- the random order of the answers is stored here }, -- more questions here }   -- randomly order all questions local function randomizeAnswers(questions) local insert, remove, random = table.insert, table.remove, math.random   for q = 1, #questions do local question = questions[q] -- next question to order randomly   local available = {} local order = {} -- we will store our order here   -- generate the default order local numQuestions = #question.answers for i = 1, numQuestions do insert(available, i) end   -- generate the randomized order for i = 1, numQuestions do local n = random(1, #available) -- throw a random number from 1 to the number of available answers insert(order, remove(available, n)) -- remove the randomly chosen answer and add it to the order list end   question.order = order -- save the new random order end end   for i = 1, 9 do randomizeAnswers(questions) -- mix them up   local question = questions[1] -- print out the results local order = question.order local s = "" for i = 1, #order do s = s .. order[i] .. ", " end print(s) end```

Likes: pie

+1 -1 (+1 / -0 ) Share on Facebook
• Member
edited November 2017
Actually in my example above you wouldn't even need to have the bool to signify which answer was correct. Instead always put the correct answer as the first in the answer list as the order they will be displayed will always be random

EDIT: Updated the above code to support this theory
Sign In or Register to comment.