简体   繁体   中英

Generate random display of array elements in an array of arrays?

Ok, i have an array that contains at least two or more arrays that can contain several objects:

array[ [array[n], array[n], array[n], etc...]

my question is how to loop through and randomly pick one object from lets say array[0][1] and randomly pick another object from array[0][15] and produce no duplicates while appending each one to the page.

I have an example of what i am working on here http://jsfiddle.net/I_am_Chris/Yn5Wy/

    var randObj1;
    var randObj2;
    var randArray;
    for(i=o; i<array.length; i++){
       randArray = array[i]; //get length of "nested" arrays within the array

      for(n=0;n<randArray.length; n++){
           randObj1 = [][].name
           randObj2 = [][].name
      }
    }

I have tried shuffling the arrays, but that just shuffles the individual arrays, but not the outcome i need.

OK, it sounds like you want N pairs of two choices where each item in the pair is from a different array and you want no repeats.

The no repeats part is going to be efficient and run less risk of infinite looping if you create a parallel data structure that we can remove items from once chosen. This is flatly the simplest way to avoid duplicatesw without having to do a search each time. It also allow you to easily know how many choices are left in any given array in case there are no more possibilities. Here's how you could do that:

function getPairs(origData, N) {

    // make copy of the data we can modify to keep track of which choices are used
    var copyData = [];
    for (var i = 0; i < origData.length; i++) {
        copyData.push(origData[i].slice(0));
    }

    function getRandomValueAndRemove(skipArray) {
        var randArray;
        // select an array that isn't skipArray
        do {
            randArray = Math.floor(Math.random() * copyData.length);
        } while (randArray === skipArray) ;

        // select an item in that array
        var randIndex = Math.floor(Math.random() * copyData[randArray].length);
        var value = copyData[randArray][randIndex];

        // remove that item from copyData
        copyData[randArray].splice(randIndex, 1);

        // if one of the arrays we selected is now empty, then remove it
        if (!copyData[randArray].length) {
            copyData.splice(randArray, 1);
            // this array is gone so we don't have to worry about selecting it again
            randArray = -1;
        }

        // return data and which array it is
        return {value: value, whichArray: randArray};
    }

    // get N pairs
    var pairs = [];

    for (i = 0; i < N && copyData.length > 1; i++) {
        var item1 = getRandomValueAndRemove();
        var item2 = getRandomValueAndRemove(item1.whichArray);
        pairs.push([item1.value, item2.value]);
    }

    // pairs contains an array of pairs
    // where each item in a pair is from a different source array
    // like this
    //  [[a, b], [c,d], [e,f]]
    return pairs;
}

Working demo: http://jsfiddle.net/jfriend00/sy6XF/


If the pairs can contain any two objects, then it's simpler to do it like this.

You have some data that looks like this (array of arrays):

var origData = [[...], [...], [...]];

You can create a temporary single flat array with all the objects in it. Generate one random number to get an object. Then, remove that object from the temporary array and repeat the process (with a now shorter array). This is the simplest way of avoiding duplicates because you remove the ones you've used from the temporary array and select random choices from the remaining elements.

Here's a code example for the second option:

var origData = [[...], [...], [...]];
var flatData = [];
var item;

// put everything into flatData
for (var i = 0; i < origData.length; i++) {
    flatData.push.apply(flatData, origData[i]);
}

var pairs = [];
// now select N random pairs
for (var i = 0; i < N && flatData.length > 1; i++) {
    var rand = Math.floor(Math.random() * flatData.length));
    var obj1 = flatData[rand];

    // now remove that element from flatData so we won't pick it again
    flatData.splice(rand, 1);    

    // get second randome value
    rand = Math.floor(Math.random() * flatData.length));
    var obj2 = flatData[rand];

    pairs.push([obj1, obj2]);
}

// pairs contains an array of pairs
[[a, b], [c,d], [e,f]]

to generate a random number, use Math.random() Math.random() generates a random number between 0 and 1. Then multiply by the length of the nested array to generate an index for the element you want from the nested array. Repeat the random number generation for the second index as long as it's equal to the first index. Store the results in the results array.

var results = [];
var genRandNum = function(max) {
  return Math.random() * (max - 1);
}

for(var i = 0; i < array.length; i++) {
  var nestedArray = array[i];

  var randIndex1 = genRandNum(nestedArray.length);
  results.push(nestedArray[randIndex1]);
  do {
    var randIndex2 = genRandNum(nestedArray.length);
  } while (randIndex1 === randIndex2);
  results.push(nestedArray[randIndex2]);
  return results;
}

FYI, didn't test this because it wasn't clear what your test should produce.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM