Reputation: 598
I need some help here please.
So I have the following array:
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
I am trying to split this array into chunks with lengths between a given range
const minChunkSize = 2;
const maxChunkSize = 5;
So the chunk size can be anything between minChunksize
and maxChunkSize
randomly generated.
Possible outputs:
[[1, 2, 3], [4, 5, 6, 7], [8, 9, 10]]
or
[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
or
[[1, 2], [3, 4, 5, 6, 7], [8, 9, 10]]
or
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
etc...
Thank you for your help!
Upvotes: 0
Views: 1160
Reputation: 17190
This is a little inefficient, but you can create a recursive method that progressively slice() a random number (between some min
and max
) of elements from the array. If the final generated result have some() array with a length less than the minimum, then the method recall itself.
const randSplit = (arr, min, max) =>
{
// Check arguments.
if (min > arr.length || max <= min)
return [arr];
let res = [], i = 0, rnd;
while (i < arr.length)
{
rnd = Math.floor(Math.random() * (max - min)) + min;
res.push(arr.slice(i, i + rnd));
i += rnd;
}
if (res.some(x => x.length < min))
return randSplit(arr, min, max)
else
return res;
}
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
console.log(JSON.stringify(randSplit(arr, 2, 5)));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
Upvotes: 5
Reputation: 1631
Even though this is not the most efficient solution, you can try to generate the chunks and if the last item is shorter than the minimum required value, you try to generate it again (recursion) like so:
const generate = (input, min, max) => {
const random = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
const inner = arr => {
if (arr.length === 0) return;
const minIndex = arr.length < min ? arr.length : min;;
const maxIndex = arr.length < max ? arr.length : max;
const splitIndex = random(minIndex, maxIndex);
const generatedArray = arr.slice(0, splitIndex);
const remainingArray = arr.slice(splitIndex);
if (remainingArray.length === 0) {
return [generatedArray];
} else {
return [generatedArray].concat(inner(remainingArray));
}
};
const result = inner(input);
return result.every(item => item.length >= min) ? result : generate(input, min, max);
};
console.log(
generate(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
2,
4,
)
);
Upvotes: 2
Reputation: 55
A recursive function will do the job:
var N = 150;
var test = Array.apply(null, {length: N}).map(Number.call, Number);
console.log('inputArray', test);
var minChunkSize = 2;
var maxChunkSize = 5;
function chunk(inputArray, minChunkSize, maxChunkSize) {
if(inputArray.length <= maxChunkSize) {
return inputArray;
}
return inputArray.splice(0, Math.round(Math.random() * (maxChunkSize - minChunkSize)) + minChunkSize);
}
function chunkAll(inputArray, minChunkSize, maxChunkSize) {
var ret = [];
while(inputArray.length > maxChunkSize) {
ret.push(chunk(inputArray, minChunkSize, maxChunkSize));
}
if(inputArray.length > 0) {
ret.push(inputArray);
}
return ret;
}
console.log('chunked', chunkAll(test, minChunkSize, maxChunkSize));
Upvotes: 1