0

I have to sort 3 arrays using jquery but order of the result should be same

The fist array is for text answers second is for Image answer and third is for Audio answer after sorting all array should be in same order , but It have to sort when question change

var Textanswers = plugin.config.randomSort || plugin.config.randomSortAnswers ?
question.a.sort(function () { return (Math.round(Math.random()) - 0.5); }) :
question.a;

var Imageanswer= plugin.config.randomSort || plugin.config.randomSortAnswers ?
 question.imga.sort(function () { return (Math.round(Math.random()) - 0.5); }) :
 question.imga;


var Audioanswer= plugin.config.randomSort || plugin.config.randomSortAnswers ?
question.auda.sort(function () { return (Math.round(Math.random()) - 0.5); }) :
question.auda;

2 Answers2

0

One way to do this is to use an array of indices, and shuffle that instead.

Then you can use the indices in the shuffled array to access the elements of each of the other arrays in the same random order.

The following C# code demonstrates the approach (along with a standard shuffle algorithm):

using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo
{
    class Program
    {
        static void Main()
        {
            int[]    array1 = {1, 2, 3, 4, 5};
            string[] array2 = {"One", "Two", "Three", "Four", "Five"};
            double[] array3 = {0.1, 0.2, 0.3, 0.4, 0.5};

            // Create an array of indices the same length as the arrays to be shuffled.

            var indices = Enumerable.Range(0, array1.Length).ToArray();

            // Shuffle the indices.

            Shuffle(indices, new Random());

            // Now you can use the shuffled indices to access all the arrays in the same random order:

            foreach (int index in indices)
            {
                Console.WriteLine($"{array1[index]}, {array2[index]}, {array3[index]}");
            }
        }

        // Standard shuffle.
        public static void Shuffle<T>(IList<T> array, Random rng)
        {
            for (int n = array.Count; n > 1;)
            {
                int k = rng.Next(n);
                --n;
                T temp = array[n];
                array[n] = array[k];
                array[k] = temp;
            }
        }
    }
}
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
0

There are many ways to shuffle an array, but I'll use yours in this answer:

const shuffle = xs => xs.sort(() => Math.round(Math.random()) - 0.5));

Your question contains 3 arrays of similar length. The items in the array are "related" to each other by index:

question.a[i] ~ question.imga[i] ~ question.auda[i]

One way to make sure these relations are respected when shuffling, is to shuffle "trios" of items rather than the individual arrays.

shuffle([
  [question.a[0], question.imga[0], question.auda[0]],
  /* ... */
])

This leaves two challenges: 1. Create one array of related items from several arrays 2. After sorting, extract the individual arrays from the shuffled trios

1. Zipping

Let's define a zip function:

const zip = (xs, ...others) =>
  xs.map(
    (x, i) => [x].concat(others.map(ys => ys[i]))
  );
  
console.log(zip([1, 2, 3], ["a", "b", "c"], ["I", "II", "III"]));

2. Extracting

Now, to get back to the three separate arrays, we create a "question constructor" that takes an array of [a, imga, auda] and converts it to an object with named properties:

const Question = ([a, imga, auda]) => ({ a, imga, auda })

or, more generic:

const zipped = [[1, "a", "I"], [2, "b", "II"], [3, "c", "III"]];

const unzip = xss => xss.reduce(
  (t1, t2) => t1.map((x, i) => [].concat(x).concat(t2[i]))
);

console.log(unzip(zipped));

Putting them together:

const q = {
  question: "Are my answers shuffled?",
  answers: [ "Yes", "No", "Maybe" ],
  audio: [ "yeeeeaaah", "naaaa", "ehhhh" ],
  img: [ "✔", "⛔️", "❓" ]
};

// Utils
const zip = (xs, ...others) =>
  xs.map(
    (x, i) => [x].concat(others.map(ys => ys[i]))
  );

const unzip = xss => xss.reduce(
  (t1, t2) => t1.map((x, i) => [].concat(x).concat(t2[i]))
);

const shuffle = xs => xs.sort(() => Math.random() - 0.5)

// Question shuffler implementation
const shuffleQuestion = q => {
  const [answers, audio, img] =
    unzip(shuffle(zip(q.answers, q.audio, q.img)));
    
  return Object.assign(
    {}, q, { answers, audio, img }
  );
};

// Three versions of the question that *might* have 
// differently ordered answers
console.log(shuffleQuestion(q));
console.log(shuffleQuestion(q));
console.log(shuffleQuestion(q));
  

Of course, you can also create a javascript implementation of the approach presented by Matthew:

const reorder = order => xs => order.map(i => xs[i]);
const range = length => Array.from({ length }, (_, i) => i);
const shuffle = xs => xs.sort(() => Math.random() - 0.5);

const myShuffle = reorder(shuffle(range(3)));

console.log(myShuffle([1, 2, 3]));
console.log(myShuffle(["a", "b", "c"]));
console.log(myShuffle(["I", "II", "III"]));
user3297291
  • 22,592
  • 4
  • 29
  • 45