Question

I am working on this little app and I have an array of more than 100 objects which I want to split in groups. The tricky part is that I want my newly created arrays to contain random number of objects. For example:

initial: ["a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15", "a16", "a17", "a18", "a19"]

modified: ["a0", "a1", "a2"], ["a3", "a4", "a5", "a6", "a7"], ["a8"], ["a9", "a10"]...

I think you get the idea. I was stuck with this for the last few hours and I just can't figure it out.

I hope you can help me! Thanks a lot

Was it helpful?

Solution

Since you didn't specify minimum number of arrays or min/max elements per array, here's a general purpose function that you can specify min/max elements for each array. Note though that this doesn't strictly enforce min elements, and indeed it may be impossible to 100% do, depending on how many elements there are in the original array vs. how many are randomly assigned to each array element. For example if you have 10 elements original and you do min 2 max 4, you could end up with 3/3/3/1, because the min will be enforced up until there's not enough to enforce. You didn't really give any "rules" about that.

min and max are both optional and default to 1. If only min is specified, max will default to min.

also note that since arrays are passed by reference, this will by default "empty" the original array. If you want to preserve the original array, uncomment the first line in the function (obviously n/a if you opt to prototype it).

function randChunkSplit(arr,min,max) {
  // uncomment this line if you don't want the original array to be affected
  // var arr = arr.slice();
  var arrs = [],size=1; 
  var min=min||1;
  var max=max||min||1;
  while (arr.length > 0) {
    size = Math.min(max,Math.floor((Math.random()*max)+min));
    arrs.push(arr.splice(0, size));
  }
  return arrs;
}

examples

var letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];

// randChunkSplit(letters)
[["a"], ["b"], ["c"], ["d"], ["e"], ["f"], ["g"], ["h"], ["i"], ["j"], ["k"], ["l"], ["m"], ["n"], ["o"], ["p"], ["q"], ["r"], ["s"], ["t"], ["u"], ["v"], ["w"], ["x"], ["y"], ["z"]]

// randChunkSplit(letters,3)
[["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"], ["j", "k", "l"], ["m", "n", "o"], ["p", "q", "r"], ["s", "t", "u"], ["v", "w", "x"], ["y", "z"]]

// randChunkSplit(letters,1,3)
[["a"], ["b", "c"], ["d", "e"], ["f", "g", "h"], ["i", "j", "k"], ["l"], ["m"], ["n", "o"], ["p", "q"], ["r"], ["s", "t"], ["u", "v", "w"], ["x", "y", "z"]]

// randChunkSplit(letters,2,3) 
[["a", "b", "c"], ["d", "e", "f"], ["g", "h"], ["i", "j", "k"], ["l", "m", "n"], ["o", "p", "q"], ["r", "s", "t"], ["u", "v", "w"], ["x", "y", "z"]]

// randChunkSplit(letters,2,3)
// same thing as before, but notice how this time we end up with just 1 elem left over
[["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"], ["j", "k", "l"], ["m", "n", "o"], ["p", "q"], ["r", "s"], ["t", "u", "v"], ["w", "x", "y"], ["z"]]

Alternatively, you could prototype it to Array if you want, something like this:

Array.prototype.randChunkSplit = function (min,max) {
  var arrs = [],size=1; 
  var min=min||1;
  var max=max||min||1;
  while (this.length > 0) {
    size = Math.min(max,Math.floor((Math.random()*max)+min));
    arrs.push(this.splice(0, size));
  }
  return arrs;
}

var letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];

letters.randChunkSplit(1,4)

OTHER TIPS

Here's a framework for what you might want to do:

var initial = ["a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10"];
var modifiedArrays = [];
var totalItems = 0
var arraySize = 1

while (totalItems < initial.length) {
    if ((initial.length - totalItems) <= 30)}
        arraySize = initial.length - totalItems
        totalItems += arraySize
    }
    else
    {
        arraySize = Math.floor((Math.random()*30)+1);
        totalItems += arraySize
    }

    modifiedArrays.push(initial.slice(totalItems - arraySize, arraySize + 1));
}

Diclaimer: I have very little experience with JavaScript and this code is completely untested, so pardon any errors. Also, this script takes chunks of between 1 and 30 elements.

I made a few assumptions, namely, that there was no set size to the amount of arrays or a minimum size.

var original = ["a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15", "a16", "a17", "a18", "a19"];

var results = [];

var breaker = function(arr){
   if(arr.length === 0){
      return;
   }
   var pieceSize = Math.floor(Math.random()*arr.length) + 1,
       result = arr.splice(0, pieceSize);
   results.push(result);
   breaker(arr);   
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top