0

I have three arrays in javascript, for example:

one = [1,2,3,4];
two = [5,6,7,8];
three = [9,10,11,12];

And then if I were to call shuffle(one,two,three) then it may produce

one = [2,3,1,4];
two = [6,7,5,8];
three = [10,11,9,12];

See how the 2,6, and 10 stlil align and all three have the same index, for example? This is what I mean by keeping the numbers associated with each other in the other lists.

How can I write that shuffle function as defined above?

CodeGuy
  • 28,427
  • 76
  • 200
  • 317
  • What...not sure who changed it to sort. There is no sorting here. – CodeGuy Oct 03 '13 at 23:57
  • The easiest and "most universal" way is to map onto a single object per index, perform the sort/shuffle, and map back. Of course, if you can start with: values = [{one:, two:, three:}, {..}], then it'll likely be easier throughout. – user2246674 Oct 03 '13 at 23:58
  • @CodeGuy You can replace "shuffle" with "sort" and the end result is the same (excluding the ordering function). I know I've seen the same with sorting before (sorting was also an original tag). – user2246674 Oct 03 '13 at 23:58
  • @user2246674 no...that is incorrect. – CodeGuy Oct 03 '13 at 23:58
  • @CodeGuy Consider that a [naive] shuffle can be implemented as a sort with a random ordering function - it is the *same* fundamental problem with association. Also, look at the original tags (that I didn't add). – user2246674 Oct 03 '13 at 23:59
  • Yes, that is correct when you add that EXTREMELY important part :) – CodeGuy Oct 03 '13 at 23:59
  • @user2246674 can you demonstrate how this would be done? I don't know how to use maps in javascript – CodeGuy Oct 04 '13 at 00:00
  • This question has been asked before, http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array. – Jon Koops Oct 04 '13 at 00:00
  • @CodeGuy See the posted answer, map = "transform" in that context :) – user2246674 Oct 04 '13 at 00:01
  • @Jon: no, not really. It certainly covers the first part (shuffling the array), but not the second part (retaining the index-correlation between the shuffled arrays). – David Thomas Oct 04 '13 at 00:06
  • @DavidThomas Ah I see, didn't quite pick that up from the question. – Jon Koops Oct 04 '13 at 00:10
  • @CodeGuy I assume all arrays have the same length? – Jon Koops Oct 04 '13 at 00:12

1 Answers1

1
zip = function() {
    var args = [].slice.call(arguments, 0);
    return args[0].map(function(_, i) {
        return args.map(function(a) {
            return a[i]
        })
    })
}

unzip = function(a) {
    return a[0].map(function(_, i) {
        return a.reduce(function(y, e) {
            return y.concat(e[i])
        }, [])
    })
}

shuffle = function(a) {
    for (var i = a.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
    return a;
}

z = unzip(shuffle(zip(one, two, three)))
one = z[0]
two = z[1]
three = z[2]

A little verbose, but works...

Another option, perhaps faster in this case:

range = function(n) {
    for(var r = [], i = 0; i < n; i++)
        r.push(i);
    return r;
}

pluck = function(a, idx) {
    return idx.map(function(i) {
        return a[i];
    });
}

r = shuffle(range(one.length))
one = pluck(one, r)
two = pluck(two, r)
three = pluck(three, r)

Also, it would be better to have an array of arrays instead of three variables:

matrix = [
    [1,2,3,4],
    [5,6,7,8],
    [9,10,11,12]
];

r = shuffle(range(matrix[0].length));
matrix = matrix.map(function(row) {
    return pluck(row, r)
});
georg
  • 211,518
  • 52
  • 313
  • 390
  • Shouldn't you have the `var` keyword in front of your functions, as well as in front of the `z`, `one` `two` and `three` variables? – Jon Koops Oct 04 '13 at 00:02