Javascript | Как сохранить порядок после рандомизации массива

#javascript #arrays

#javascript #массивы

Вопрос:

После рандомизации массива элементов вопроса я пытаюсь сохранить новые индексы элементов.

Я использую массив, вызываемый idMap для достижения этой цели. Он сохраняет исходный индекс в первом цикле for, а затем обновляет индекс после того, как массив элементов вопроса был перетасован.

Есть ли лучший способ сделать это без сохранения порядка в качестве атрибута вопроса ( questionInstances[i].originalOrder ), поскольку он может быть перезаписан?

   // 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;
    }

  }
 

Ответ №1:

Давайте сначала сопоставим questionInstances новый массив кортежей (первый элемент которого является исходным элементом в массиве, а второй элемент — его индексом):

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

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

Элементы в этом массиве:

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

Мы сопоставили наш оригинал questionInstances с новым массивом (который содержит их индексы) без изменения (изменения) его элементов.

Теперь перетасуйте этот массив:

 tuples = H5P.shuffleArray(tuples)
 

Теперь перетасованный questionInstances массив:

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

И отображение индекса:

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

Бонус: вы можете получить questionInstances и idMap за один шаг, используя reduce :

 let [shuffledQuestionInstances, idMap] = tuples.reduce(
    (acc, [o, i]) => [acc[0].concat([o]), acc[1].concat([i])], 
    [[],[]]
  )
 

Комментарии:

1. Отличный ответ, все еще обдумываю это. Кроме того, какова наилучшая практика при использовании ‘var’ против ‘let’?

2. Я думаю, вы можете найти много сообщений об этом в Интернете. Обычно избегайте var всегда. Я сам тоже не использую let . Здесь мы смогли переназначить tuples = H5P.shuffleArray(tuples) , потому tuples что это let переменная. Если бы мы использовали const tuples = questionInstances... , то пришлось бы повторно присвоить новое имя переменной перетасованному массиву, например: const stuples = H5P.shuffleArray(tuples) .

3. map функция, которую мы использовали здесь, работает в ES5 и ES6 и более поздних версиях. let переменные введены в ES6, но вы можете заменить их на var те, которые работают в более ранних версиях.

4. В ES5 вам необходимо изменить синтаксис анонимной функции, например: tuples = questionInstances.map(function(o, i) { return [o, i] })

Ответ №2:

Вы могли бы просто использовать хэш-таблицу с ограниченной областью действия, предполагая, что экземпляры вопроса имеют уникальные идентификаторы.

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

Комментарии:

1. К сожалению, экземпляры вопроса не имеют уникальных идентификаторов.