0

After randomizing an array of question elements I am trying to save the new indexes of the elements.

I use an array called idMap to do achieve this. It saves the original index in the first for loop then updates the index once the question elements array has been shuffled.

Is there better way to do this without saving the order as an attribute of the question (questionInstances[i].originalOrder) as it may be overwritten?

  // Save the original order of array
  for (var i = 0; i < questionInstances.length; i++) {
    questionInstances[i].originalOrder = i;
    idMap[i] = i;
  }

  // Randomize array

  if (params.randomQuestions) {

    questionInstances = H5P.shuffleArray(questionInstances);

    // Save new randomized order
    for (var i = 0; i < questionInstances.length; i++) {
      idMap[i] = questionInstances[i].originalOrder;
    }

  }
0

2 Answers 2

1

Let's first map questionInstances to a new array of tuples (which their first element is the original item in the array and the second element is its index):

let questionInstances = ["a", "b", "c", "d", "e"] // for example

let tuples = questionInstances.map((o, i) => ([o, i]))

The items in this array are:

[["a", 0], ["b", 1], ["c", 2], ["d", 3], ["e", 4]]

We mapped our original questionInstances to a new array (which contains their indices) without modifying (mutating) its elements.

Now shuffle this array:

tuples = H5P.shuffleArray(tuples)

Now the shuffled questionInstances array is:

questionInstances = tuples.map(d => d[0])

And the index map:

let idMap = tuples.map(d => d[1])

Bonus: you can get questionInstances and idMap in a single step using reduce:

let [shuffledQuestionInstances, idMap] = tuples.reduce(
    (acc, [o, i]) => [acc[0].concat([o]), acc[1].concat([i])], 
    [[],[]]
  )
Sign up to request clarification or add additional context in comments.

4 Comments

Great answer, still wrapping my head around it. As an aside, what is best practice when using 'var' vs 'let'?
I think you can find many posts online on this. Generally avoid var always. I myself don't use let either. Here we've been able to re-assign tuples = H5P.shuffleArray(tuples) because tuples is a let variable. If we had used const tuples = questionInstances... then had to re-assign a new variable name to the shuffled array, for example: const stuples = H5P.shuffleArray(tuples).
map function that we used here works in ES5 and ES6 and later versions. let variables is introduced in ES6, but you can replace them with var which work in earlier versions.
In ES5, you need to change the anonymous function syntax to for example: tuples = questionInstances.map(function(o, i) { return [o, i] })
0

You could just use a scoped hash table, assuming the question instances have unique ids.

// update this as needed
var hash = {
    //id: order
};

1 Comment

Unfortunately the question instances do not have unique id's.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.