0

I am pulling data from an API that gives me an object of items, each containing a string named correct_answer and an array named incorrect_answers.

I am trying to combine those values within each item, so when I do v-for, it will loop through the answers merged together in one loop. I also want to randomize the order of those answers.

An example of what the object looks like:

"results": [
    {
      "question": "Where was the Games of the XXII Olympiad held?",
      "correct_answer": "Moscow",
      "incorrect_answers": [
        "Barcelona",
        "Tokyo",
        "Los Angeles"
      ]
    },
    {
      "question": "What is the first weapon you acquire in Half-Life?",
      "correct_answer": "A crowbar",
      "incorrect_answers": [
        "A pistol",
        "The H.E.V suit",
        "Your fists"
      ]
    },
]
tony19
  • 125,647
  • 18
  • 229
  • 307
user9664977
  • 789
  • 2
  • 15
  • 28

3 Answers3

1

var res = [
    {
      "question": "Where was the Games of the XXII Olympiad held?",
      "correct_answer": "Moscow",
      "incorrect_answers": [
        "Barcelona",
        "Tokyo",
        "Los Angeles"
      ]
    },
    {
      "question": "What is the first weapon you acquire in Half-Life?",
      "correct_answer": "A crowbar",
      "incorrect_answers": [
        "A pistol",
        "The H.E.V suit",
        "Your fists"
      ]
    },
]

var answers = res.map(i => [i.correct_answer, ...i.incorrect_answers])

console.log(answers[0])
console.log(answers[1])
NaN
  • 1,955
  • 13
  • 16
0

let merged = [item.correct_answer, ...item.incorrect_answers], or am I missing something?

mbojko
  • 13,503
  • 1
  • 16
  • 26
  • That won't work as you'd expect: `[[1,2], ...[3,4]]` → `[[1,2],3,4]` – Nino Filiu Mar 25 '19 at 20:21
  • 1
    In the OP, `correct_answer` isn't an array, it's a value. – mbojko Mar 25 '19 at 20:22
  • @mbojko yes you are correct I misspoke when I said two arrays it would be an array and a value. And I think the thing I am getting hung up on is would I need to do this as a computed property? And then do a v-for loop on results of that computed property? – user9664977 Mar 25 '19 at 20:25
0

You could 1️⃣spread the incorrect_answers into a new array with correct_answer, and then 2️⃣ attach the result as a new property on the original data. Additionally, 3️⃣ you could shuffle the answers while you're at it:

const newData = data.map(x => {
  const answers = [x.correct_answer, ...x.incorrect_answers] /*1️⃣*/
  x.answers /*2️⃣*/ = shuffle(answers) /*3️⃣*/
  return x
})

This new array could be used as a computed property (e.g., named questions) in your template:

<fieldset v-for="q in questions" :key="q.question">

const rawData = {
  "results": [
    {
      "question": "Where was the Games of the XXII Olympiad held?",
      "correct_answer": "Moscow",
      "incorrect_answers": [
        "Barcelona",
        "Tokyo",
        "Los Angeles"
      ]
    },
    {
      "question": "What is the first weapon you acquire in Half-Life?",
      "correct_answer": "A crowbar",
      "incorrect_answers": [
        "A pistol",
        "The H.E.V suit",
        "Your fists"
      ]
    },
  ]
}

new Vue({
  el: '#app',
  data() {
    return {
      rawData: rawData.results
    }
  },
  computed: {
    questions() {
      return this.rawData.map(x => {
        const answers = [x.correct_answer, ...x.incorrect_answers]
        x.answers = shuffle(answers)
        this.$set(x, 'answer', null) // create reactive answer prop
        return x
      })
    }
  }
})

// https://stackoverflow.com/a/2450976/6277151
function shuffle(array) {
  let currentIndex = array.length, temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}
<script src="https://unpkg.com/vue@2.6.10"></script>

<div id="app">
  <form action="#">
    <fieldset v-for="(q,i) in questions" :key="q.question">
      <h2>{{q.question}} {{q.answer}}</h2>
      
      <div v-for="a in q.answers" :key="a">
        <label>
          <input type="radio" :name="i" :value="a" @change="q.answer = a">
          <span>{{a}}</span>
        </label>
      </div>
    </fieldset>
  </form>
</div>
tony19
  • 125,647
  • 18
  • 229
  • 307