I want to use a json file with a list containing a...
# android
m
I want to use a json file with a list containing a lot of lists. Each child list contains two unicode strings. I want to be able to access a random list using my Android app
c
@Minty Start with a small representation of your data structure, e.g.:
Copy code
{
  "questions": [
    {
      "q": "q1",
      "a": [
        "a1",
        "a2",
        "a3"
      ],
      "ca": 1
    },
    {
      "q": "q2",
      "a": [
        "a1",
        "a2",
        "a3"
      ],
      "ca": 0
    }
  ]
}
And get your system parsing that correctly, then work on selecting random questions from that
then you can scale up and figure out how things may work
you might find, if you have tons of questions, it will be worth while ingesting them into a SQLite database instead of parsing JSON every time you want to get a selection of questions
m
Copy code
[["Q1.\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Discussion Method can be used when: \n (A) The topic is very difficult\u00a0 (B) The topic is easy \n (C) The topic is difficult\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (D) All of the above \n ", "C"], ["Q2.\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Which of the following is a teaching aid? \n (A) Working Model of Wind Mill\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (B) Tape Recorder \n (C) 16mm Film Projector\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (D) All the above \n ", "D"],
My data is more like this
c
what do you think of the data structure?
m
It's like [["Question1 and choices", "Answer"],["Q2","A"]
c
are you in control of the data structure?
or has a client given it you?
m
It's a question paper data that I extracted using regex from a text file
I converted it to json in Python
Copy code
data = []

for r in re.findall(r"Q\d+.*?(?=Q\d+)", soup.text, flags=re.S):

    data_qa = []

    rs = re.findall(r"Q\d+.*?(?=Answer.*?\:.*?[a-dA-D])", r.strip(), flags=re.S)
    ra = re.findall(r"Answer.*?\:.*?[a-dA-D]", r.strip(), )

    for rse in rs:
   #     print rse
        data_qa.append(rse)



    for rsa in ra:
        if ra.index(rsa) == 0:
#            print("The answer is "+ rsa.replace("Answer", "").replace(":", "").strip())
            data_qa.append(rsa.replace("Answer", "").replace(":", "").strip())
  #  print "__________________________________________________________________"
    data.append(data_qa)

for d in data:
    if len(d)<2:
        data.remove(d)
        print d

jdump = json.dumps(data)

with file("qNa.json", "w+") as f:
    f.write(jdump)
c
ok cool, I would recommend for your own sanity sticking with either \u00a0 or \n but not both 😄
this shouldn’t be too tough though
each of the questions could be represented nicely using a
data class Question(val question:String, val answer:String)
m
So is the above representation any good for quiz type things
[["Question1 and choices", "Answer"],["Q2","A"]
c
given that you’re scraping it from a text block, it’ll have to do
the reason I was digging was, if you had the data in a format of question and then a list of answers and the correct answer
you could make the quiz more dynamic and randomise the order of answers etc
but since the question answers are encoded in the question, that’s not really viable
m
I'm supposed to create the
data class
outside
oncreate
right? Can I do it in the main activity classs?
c
you can yeah
m
But I can call data using
index
in a list. How do I do that with a data class. I still don't understand the concept of data class. i guess I'll have to look it up
c
Copy code
class MainActivity : AppCompatActivity() {

    data class Question(val question: String, val answer: String)

    fun parseQuestions(rawQuestionJson: String): List<Question> {
        TODO("Parse json")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        parseQuestions("[[\"Question 1\",\"A\"],[\"Question 2\",\"B\"]]")
    }
}
for example
so if you imagine
class Question(val question:String, val answer:String)
if I did
Copy code
val q1 = Question("q1", "a")
val q2 = Question("q1", "a")
if (q1 == q2) {
   println("They are equal")
}
‘they are equal’ would not be printed
if I used a data class, kotlin will provide equality methods making that pass
data classes are useful for identifying clumps of data that have a particular meaning
once you parse the JSON, you can then go about randomising access to the list
m
How do I dynamically create q1, q2? Would I parse json on the fly and get the data index I want and assign it to q1
data[2] #question3
c
how many questions are you dealing with?
m
I did a len(data) there seem to be 1457
c
that’s an impressive amount of questions
you wouldn’t want to parse that everytime you wanted a question
m
Question papers from 2004 -2017 lol
c
I’d definitely consider whacking the questions in a database, BUT
you should be able to get away with
Copy code
private fun parseQuestions(rawQuestionJson: String): List<Question> {
        val result = mutableListOf<Question>()
        val questionArray = JSONArray(rawQuestionJson)
        for (i in 0..questionArray.length()) {
            val question = questionArray.getJSONArray(i)
            result += Question(question.getString(0), question.getString(1))
        }
        return result
    }
line by line, we create a mutable list to store questions in. We then parse the input JSON (we know it’s a JSONArray) We then iterate over all the child arrays We then add a new Question object to our result list (which we can do because it’s mutable) consisting of the two strings in the child question json array object We then result the result
m
So, you add created Question object instances to list. That was what was bothering me. Thanks. BTW is JSONArray an inbuilt function?
c
Copy code
class MainActivity : AppCompatActivity() {

    data class Question(val question: String, val answer: String)

    private fun parseQuestions(rawQuestionJson: String): List<Question> {
        val result = mutableListOf<Question>()
        val questionArray = JSONArray(rawQuestionJson)
        for (i in 0..questionArray.length()) {
            val question = questionArray.getJSONArray(i)
            result += Question(question.getString(0), question.getString(1))
        }
        return result
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var tenQuestions = parseQuestions("[[\"Question 1\",\"A\"],[\"Question 2\",\"B\"]]").shuffled().take(10)
        
        TODO("Display ten questions")
    }
}
JSONArray is part of
org.json
which is shipped with android
var tenQuestions = parseQuestions("[[\"Question 1\",\"A\"],[\"Question 2\",\"B\"]]").shuffled().take(10)
may look like black magic but
Copy code
var tenQuestions = parseQuestions("...JSONHERE...")
   .shuffled() // Randomises the order of list items
   .take(10) // Take the first 10 items from the list
assuming you want a random collection of questions!
subjecting someone to 1407 questions is going to be brutal lol
if this is to help you revise etc
I would really investigate the possibility of teasing out the answer from the questions
it’ll help you learn the right answer, rather than the right letter 😉
m
It's a multiple choice. I have created logic for buttons. I check the string A, B,C,D and set the answer int to ,1,2,3,4 and check in Button
What do you mean by teasing out?
c
so if all the questions take the format
“This is a question that needs to be answered by one of the following answers: A) Answer A B) Answer B C) Answer C D) Answer D” Correct Answer: C Then I would parse the input data to extract “This is a question that needs to be answered by one of the following answers” the individual answers The correct answer
and I’d transform that into the format I explained above
then you could randomise the display of the answers
since you know what the correct answer is, you always know that if you display answer C first, the first button would be the correct one
any who ! Lunch time, ask questions though!
m
I can maybe give a option to display answer too. But my main focus is to build a quiz. This is my first Kotlin project and I'm in love with kotlin already
Oh! You mean randomising the order of the choices?
That'll be useful but I have to parse the data first. Regex to the rescue.
But I want to build a simple working project first and add features later
Since this is my first project, I want to take it easy and build the simple parts first (a proof of concept) and add features later
BTW what do I have to import for JSONArray?
Never mind, imported it
c
your approach is perfect
build the simplest thing first
go end to end
then beef it up as you go
agile all the way 👍